diff --git a/groups.io/css/application-e223b9cc72bae00ecc93c35c77a729b2.css b/groups.io/css/application-0fdc8fb7b212ef119ea05f76b6c42703.css similarity index 90% rename from groups.io/css/application-e223b9cc72bae00ecc93c35c77a729b2.css rename to groups.io/css/application-0fdc8fb7b212ef119ea05f76b6c42703.css index 2e117618..fdfbe4ea 100644 --- a/groups.io/css/application-e223b9cc72bae00ecc93c35c77a729b2.css +++ b/groups.io/css/application-0fdc8fb7b212ef119ea05f76b6c42703.css @@ -4,12 +4,6 @@ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:"Glyphicons Halflings";src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot%3F) format("embedded-opentype"),url(../fonts/glyphicons-halflings-regular.woff2) format("woff2"),url(../fonts/glyphicons-halflings-regular.woff) format("woff"),url(../fonts/glyphicons-halflings-regular.ttf) format("truetype"),url(../fonts/glyphicons-halflings-regular.svg) format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:"Glyphicons Halflings";font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:"\2014 \00A0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:""}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:"\00A0 \2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*=col-]{padding-right:0;padding-left:0}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-right:15px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-right:-15px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:12px;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;outline:0;filter:alpha(opacity=90);opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} /*# sourceMappingURL=bootstrap.min.css.map */ -/*! - * Bootstrap v3.4.1 (https://getbootstrap.com/) - * Copyright 2011-2019 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x;background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x;background-color:#2e6da4}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -/*# sourceMappingURL=bootstrap-theme.min.css.map */ /*! * Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license (Commercial License) @@ -22,6 +16,24 @@ .fa-duotone.fa-0:after,.fad.fa-0:after{content:"\30\30"}.fa-duotone.fa-1:after,.fad.fa-1:after{content:"\31\31"}.fa-duotone.fa-2:after,.fad.fa-2:after{content:"\32\32"}.fa-duotone.fa-3:after,.fad.fa-3:after{content:"\33\33"}.fa-duotone.fa-4:after,.fad.fa-4:after{content:"\34\34"}.fa-duotone.fa-5:after,.fad.fa-5:after{content:"\35\35"}.fa-duotone.fa-6:after,.fad.fa-6:after{content:"\36\36"}.fa-duotone.fa-7:after,.fad.fa-7:after{content:"\37\37"}.fa-duotone.fa-8:after,.fad.fa-8:after{content:"\38\38"}.fa-duotone.fa-9:after,.fad.fa-9:after{content:"\39\39"}.fa-duotone.fa-fill-drip:after,.fad.fa-fill-drip:after{content:"\f576\f576"}.fa-duotone.fa-arrows-to-circle:after,.fad.fa-arrows-to-circle:after{content:"\e4bd\e4bd"}.fa-duotone.fa-chevron-circle-right:after,.fa-duotone.fa-circle-chevron-right:after,.fad.fa-chevron-circle-right:after,.fad.fa-circle-chevron-right:after{content:"\f138\f138"}.fa-duotone.fa-wagon-covered:after,.fad.fa-wagon-covered:after{content:"\f8ee\f8ee"}.fa-duotone.fa-line-height:after,.fad.fa-line-height:after{content:"\f871\f871"}.fa-duotone.fa-bagel:after,.fad.fa-bagel:after{content:"\e3d7\e3d7"}.fa-duotone.fa-transporter-7:after,.fad.fa-transporter-7:after{content:"\e2a8\e2a8"}.fa-duotone.fa-at:after,.fad.fa-at:after{content:"\40\40"}.fa-duotone.fa-rectangles-mixed:after,.fad.fa-rectangles-mixed:after{content:"\e323\e323"}.fa-duotone.fa-phone-arrow-up-right:after,.fa-duotone.fa-phone-arrow-up:after,.fa-duotone.fa-phone-outgoing:after,.fad.fa-phone-arrow-up-right:after,.fad.fa-phone-arrow-up:after,.fad.fa-phone-outgoing:after{content:"\e224\e224"}.fa-duotone.fa-trash-alt:after,.fa-duotone.fa-trash-can:after,.fad.fa-trash-alt:after,.fad.fa-trash-can:after{content:"\f2ed\f2ed"}.fa-duotone.fa-circle-l:after,.fad.fa-circle-l:after{content:"\e114\e114"}.fa-duotone.fa-head-side-goggles:after,.fa-duotone.fa-head-vr:after,.fad.fa-head-side-goggles:after,.fad.fa-head-vr:after{content:"\f6ea\f6ea"}.fa-duotone.fa-text-height:after,.fad.fa-text-height:after{content:"\f034\f034"}.fa-duotone.fa-user-times:after,.fa-duotone.fa-user-xmark:after,.fad.fa-user-times:after,.fad.fa-user-xmark:after{content:"\f235\f235"}.fa-duotone.fa-face-hand-yawn:after,.fad.fa-face-hand-yawn:after{content:"\e379\e379"}.fa-duotone.fa-gauge-simple-min:after,.fa-duotone.fa-tachometer-slowest:after,.fad.fa-gauge-simple-min:after,.fad.fa-tachometer-slowest:after{content:"\f62d\f62d"}.fa-duotone.fa-stethoscope:after,.fad.fa-stethoscope:after{content:"\f0f1\f0f1"}.fa-duotone.fa-coffin:after,.fad.fa-coffin:after{content:"\f6c6\f6c6"}.fa-duotone.fa-comment-alt:after,.fa-duotone.fa-message:after,.fad.fa-comment-alt:after,.fad.fa-message:after{content:"\f27a\f27a"}.fa-duotone.fa-bowl-salad:after,.fa-duotone.fa-salad:after,.fad.fa-bowl-salad:after,.fad.fa-salad:after{content:"\f81e\f81e"}.fa-duotone.fa-info:after,.fad.fa-info:after{content:"\f129\f129"}.fa-duotone.fa-robot-astromech:after,.fad.fa-robot-astromech:after{content:"\e2d2\e2d2"}.fa-duotone.fa-ring-diamond:after,.fad.fa-ring-diamond:after{content:"\e5ab\e5ab"}.fa-duotone.fa-fondue-pot:after,.fad.fa-fondue-pot:after{content:"\e40d\e40d"}.fa-duotone.fa-theta:after,.fad.fa-theta:after{content:"\f69e\f69e"}.fa-duotone.fa-face-hand-peeking:after,.fad.fa-face-hand-peeking:after{content:"\e481\e481"}.fa-duotone.fa-square-user:after,.fad.fa-square-user:after{content:"\e283\e283"}.fa-duotone.fa-compress-alt:after,.fa-duotone.fa-down-left-and-up-right-to-center:after,.fad.fa-compress-alt:after,.fad.fa-down-left-and-up-right-to-center:after{content:"\f422\f422"}.fa-duotone.fa-explosion:after,.fad.fa-explosion:after{content:"\e4e9\e4e9"}.fa-duotone.fa-file-alt:after,.fa-duotone.fa-file-lines:after,.fa-duotone.fa-file-text:after,.fad.fa-file-alt:after,.fad.fa-file-lines:after,.fad.fa-file-text:after{content:"\f15c\f15c"}.fa-duotone.fa-wave-square:after,.fad.fa-wave-square:after{content:"\f83e\f83e"}.fa-duotone.fa-ring:after,.fad.fa-ring:after{content:"\f70b\f70b"}.fa-duotone.fa-building-un:after,.fad.fa-building-un:after{content:"\e4d9\e4d9"}.fa-duotone.fa-dice-three:after,.fad.fa-dice-three:after{content:"\f527\f527"}.fa-duotone.fa-tire-pressure-warning:after,.fad.fa-tire-pressure-warning:after{content:"\f633\f633"}.fa-duotone.fa-wifi-2:after,.fa-duotone.fa-wifi-fair:after,.fad.fa-wifi-2:after,.fad.fa-wifi-fair:after{content:"\f6ab\f6ab"}.fa-duotone.fa-calendar-alt:after,.fa-duotone.fa-calendar-days:after,.fad.fa-calendar-alt:after,.fad.fa-calendar-days:after{content:"\f073\f073"}.fa-duotone.fa-mp3-player:after,.fad.fa-mp3-player:after{content:"\f8ce\f8ce"}.fa-duotone.fa-anchor-circle-check:after,.fad.fa-anchor-circle-check:after{content:"\e4aa\e4aa"}.fa-duotone.fa-tally-4:after,.fad.fa-tally-4:after{content:"\e297\e297"}.fa-duotone.fa-rectangle-history:after,.fad.fa-rectangle-history:after{content:"\e4a2\e4a2"}.fa-duotone.fa-building-circle-arrow-right:after,.fad.fa-building-circle-arrow-right:after{content:"\e4d1\e4d1"}.fa-duotone.fa-volleyball-ball:after,.fa-duotone.fa-volleyball:after,.fad.fa-volleyball-ball:after,.fad.fa-volleyball:after{content:"\f45f\f45f"}.fa-duotone.fa-sun-haze:after,.fad.fa-sun-haze:after{content:"\f765\f765"}.fa-duotone.fa-text-size:after,.fad.fa-text-size:after{content:"\f894\f894"}.fa-duotone.fa-ufo:after,.fad.fa-ufo:after{content:"\e047\e047"}.fa-duotone.fa-fork:after,.fa-duotone.fa-utensil-fork:after,.fad.fa-fork:after,.fad.fa-utensil-fork:after{content:"\f2e3\f2e3"}.fa-duotone.fa-arrows-up-to-line:after,.fad.fa-arrows-up-to-line:after{content:"\e4c2\e4c2"}.fa-duotone.fa-mobile-signal:after,.fad.fa-mobile-signal:after{content:"\e1ef\e1ef"}.fa-duotone.fa-barcode-scan:after,.fad.fa-barcode-scan:after{content:"\f465\f465"}.fa-duotone.fa-sort-desc:after,.fa-duotone.fa-sort-down:after,.fad.fa-sort-desc:after,.fad.fa-sort-down:after{content:"\f0dd\f0dd"}.fa-duotone.fa-folder-arrow-down:after,.fa-duotone.fa-folder-download:after,.fad.fa-folder-arrow-down:after,.fad.fa-folder-download:after{content:"\e053\e053"}.fa-duotone.fa-circle-minus:after,.fa-duotone.fa-minus-circle:after,.fad.fa-circle-minus:after,.fad.fa-minus-circle:after{content:"\f056\f056"}.fa-duotone.fa-face-icicles:after,.fad.fa-face-icicles:after{content:"\e37c\e37c"}.fa-duotone.fa-shovel:after,.fad.fa-shovel:after{content:"\f713\f713"}.fa-duotone.fa-door-open:after,.fad.fa-door-open:after{content:"\f52b\f52b"}.fa-duotone.fa-films:after,.fad.fa-films:after{content:"\e17a\e17a"}.fa-duotone.fa-right-from-bracket:after,.fa-duotone.fa-sign-out-alt:after,.fad.fa-right-from-bracket:after,.fad.fa-sign-out-alt:after{content:"\f2f5\f2f5"}.fa-duotone.fa-face-glasses:after,.fad.fa-face-glasses:after{content:"\e377\e377"}.fa-duotone.fa-nfc:after,.fad.fa-nfc:after{content:"\e1f7\e1f7"}.fa-duotone.fa-atom:after,.fad.fa-atom:after{content:"\f5d2\f5d2"}.fa-duotone.fa-soap:after,.fad.fa-soap:after{content:"\e06e\e06e"}.fa-duotone.fa-heart-music-camera-bolt:after,.fa-duotone.fa-icons:after,.fad.fa-heart-music-camera-bolt:after,.fad.fa-icons:after{content:"\f86d\f86d"}.fa-duotone.fa-microphone-alt-slash:after,.fa-duotone.fa-microphone-lines-slash:after,.fad.fa-microphone-alt-slash:after,.fad.fa-microphone-lines-slash:after{content:"\f539\f539"}.fa-duotone.fa-closed-captioning-slash:after,.fad.fa-closed-captioning-slash:after{content:"\e135\e135"}.fa-duotone.fa-calculator-alt:after,.fa-duotone.fa-calculator-simple:after,.fad.fa-calculator-alt:after,.fad.fa-calculator-simple:after{content:"\f64c\f64c"}.fa-duotone.fa-bridge-circle-check:after,.fad.fa-bridge-circle-check:after{content:"\e4c9\e4c9"}.fa-duotone.fa-sliders-up:after,.fa-duotone.fa-sliders-v:after,.fad.fa-sliders-up:after,.fad.fa-sliders-v:after{content:"\f3f1\f3f1"}.fa-duotone.fa-location-minus:after,.fa-duotone.fa-map-marker-minus:after,.fad.fa-location-minus:after,.fad.fa-map-marker-minus:after{content:"\f609\f609"}.fa-duotone.fa-pump-medical:after,.fad.fa-pump-medical:after{content:"\e06a\e06a"}.fa-duotone.fa-fingerprint:after,.fad.fa-fingerprint:after{content:"\f577\f577"}.fa-duotone.fa-ski-boot:after,.fad.fa-ski-boot:after{content:"\e3cc\e3cc"}.fa-duotone.fa-rectangle-sd:after,.fa-duotone.fa-standard-definition:after,.fad.fa-rectangle-sd:after,.fad.fa-standard-definition:after{content:"\e28a\e28a"}.fa-duotone.fa-h1:after,.fad.fa-h1:after{content:"\f313\f313"}.fa-duotone.fa-hand-point-right:after,.fad.fa-hand-point-right:after{content:"\f0a4\f0a4"}.fa-duotone.fa-magnifying-glass-location:after,.fa-duotone.fa-search-location:after,.fad.fa-magnifying-glass-location:after,.fad.fa-search-location:after{content:"\f689\f689"}.fa-duotone.fa-message-bot:after,.fad.fa-message-bot:after{content:"\e3b8\e3b8"}.fa-duotone.fa-forward-step:after,.fa-duotone.fa-step-forward:after,.fad.fa-forward-step:after,.fad.fa-step-forward:after{content:"\f051\f051"}.fa-duotone.fa-face-smile-beam:after,.fa-duotone.fa-smile-beam:after,.fad.fa-face-smile-beam:after,.fad.fa-smile-beam:after{content:"\f5b8\f5b8"}.fa-duotone.fa-light-ceiling:after,.fad.fa-light-ceiling:after{content:"\e016\e016"}.fa-duotone.fa-comment-alt-exclamation:after,.fa-duotone.fa-message-exclamation:after,.fad.fa-comment-alt-exclamation:after,.fad.fa-message-exclamation:after{content:"\f4a5\f4a5"}.fa-duotone.fa-bowl-scoop:after,.fa-duotone.fa-bowl-shaved-ice:after,.fad.fa-bowl-scoop:after,.fad.fa-bowl-shaved-ice:after{content:"\e3de\e3de"}.fa-duotone.fa-square-x:after,.fad.fa-square-x:after{content:"\e286\e286"}.fa-duotone.fa-utility-pole-double:after,.fad.fa-utility-pole-double:after{content:"\e2c4\e2c4"}.fa-duotone.fa-flag-checkered:after,.fad.fa-flag-checkered:after{content:"\f11e\f11e"}.fa-duotone.fa-chevron-double-up:after,.fa-duotone.fa-chevrons-up:after,.fad.fa-chevron-double-up:after,.fad.fa-chevrons-up:after{content:"\f325\f325"}.fa-duotone.fa-football-ball:after,.fa-duotone.fa-football:after,.fad.fa-football-ball:after,.fad.fa-football:after{content:"\f44e\f44e"}.fa-duotone.fa-user-vneck:after,.fad.fa-user-vneck:after{content:"\e461\e461"}.fa-duotone.fa-school-circle-exclamation:after,.fad.fa-school-circle-exclamation:after{content:"\e56c\e56c"}.fa-duotone.fa-crop:after,.fad.fa-crop:after{content:"\f125\f125"}.fa-duotone.fa-angle-double-down:after,.fa-duotone.fa-angles-down:after,.fad.fa-angle-double-down:after,.fad.fa-angles-down:after{content:"\f103\f103"}.fa-duotone.fa-users-rectangle:after,.fad.fa-users-rectangle:after{content:"\e594\e594"}.fa-duotone.fa-people-roof:after,.fad.fa-people-roof:after{content:"\e537\e537"}.fa-duotone.fa-arrow-square-right:after,.fa-duotone.fa-square-arrow-right:after,.fad.fa-arrow-square-right:after,.fad.fa-square-arrow-right:after{content:"\f33b\f33b"}.fa-duotone.fa-location-plus:after,.fa-duotone.fa-map-marker-plus:after,.fad.fa-location-plus:after,.fad.fa-map-marker-plus:after{content:"\f60a\f60a"}.fa-duotone.fa-lightbulb-exclamation-on:after,.fad.fa-lightbulb-exclamation-on:after{content:"\e1ca\e1ca"}.fa-duotone.fa-people-line:after,.fad.fa-people-line:after{content:"\e534\e534"}.fa-duotone.fa-beer-mug-empty:after,.fa-duotone.fa-beer:after,.fad.fa-beer-mug-empty:after,.fad.fa-beer:after{content:"\f0fc\f0fc"}.fa-duotone.fa-crate-empty:after,.fad.fa-crate-empty:after{content:"\e151\e151"}.fa-duotone.fa-diagram-predecessor:after,.fad.fa-diagram-predecessor:after{content:"\e477\e477"}.fa-duotone.fa-transporter:after,.fad.fa-transporter:after{content:"\e042\e042"}.fa-duotone.fa-calendar-circle-user:after,.fad.fa-calendar-circle-user:after{content:"\e471\e471"}.fa-duotone.fa-arrow-up-long:after,.fa-duotone.fa-long-arrow-up:after,.fad.fa-arrow-up-long:after,.fad.fa-long-arrow-up:after{content:"\f176\f176"}.fa-duotone.fa-person-carry-box:after,.fa-duotone.fa-person-carry:after,.fad.fa-person-carry-box:after,.fad.fa-person-carry:after{content:"\f4cf\f4cf"}.fa-duotone.fa-burn:after,.fa-duotone.fa-fire-flame-simple:after,.fad.fa-burn:after,.fad.fa-fire-flame-simple:after{content:"\f46a\f46a"}.fa-duotone.fa-male:after,.fa-duotone.fa-person:after,.fad.fa-male:after,.fad.fa-person:after{content:"\f183\f183"}.fa-duotone.fa-laptop:after,.fad.fa-laptop:after{content:"\f109\f109"}.fa-duotone.fa-file-csv:after,.fad.fa-file-csv:after{content:"\f6dd\f6dd"}.fa-duotone.fa-menorah:after,.fad.fa-menorah:after{content:"\f676\f676"}.fa-duotone.fa-union:after,.fad.fa-union:after{content:"\f6a2\f6a2"}.fa-duotone.fa-chevron-double-left:after,.fa-duotone.fa-chevrons-left:after,.fad.fa-chevron-double-left:after,.fad.fa-chevrons-left:after{content:"\f323\f323"}.fa-duotone.fa-circle-heart:after,.fa-duotone.fa-heart-circle:after,.fad.fa-circle-heart:after,.fad.fa-heart-circle:after{content:"\f4c7\f4c7"}.fa-duotone.fa-truck-plane:after,.fad.fa-truck-plane:after{content:"\e58f\e58f"}.fa-duotone.fa-record-vinyl:after,.fad.fa-record-vinyl:after{content:"\f8d9\f8d9"}.fa-duotone.fa-bring-forward:after,.fad.fa-bring-forward:after{content:"\f856\f856"}.fa-duotone.fa-square-p:after,.fad.fa-square-p:after{content:"\e279\e279"}.fa-duotone.fa-face-grin-stars:after,.fa-duotone.fa-grin-stars:after,.fad.fa-face-grin-stars:after,.fad.fa-grin-stars:after{content:"\f587\f587"}.fa-duotone.fa-sigma:after,.fad.fa-sigma:after{content:"\f68b\f68b"}.fa-duotone.fa-camera-movie:after,.fad.fa-camera-movie:after{content:"\f8a9\f8a9"}.fa-duotone.fa-bong:after,.fad.fa-bong:after{content:"\f55c\f55c"}.fa-duotone.fa-clarinet:after,.fad.fa-clarinet:after{content:"\f8ad\f8ad"}.fa-duotone.fa-truck-flatbed:after,.fad.fa-truck-flatbed:after{content:"\e2b6\e2b6"}.fa-duotone.fa-pastafarianism:after,.fa-duotone.fa-spaghetti-monster-flying:after,.fad.fa-pastafarianism:after,.fad.fa-spaghetti-monster-flying:after{content:"\f67b\f67b"}.fa-duotone.fa-arrow-down-up-across-line:after,.fad.fa-arrow-down-up-across-line:after{content:"\e4af\e4af"}.fa-duotone.fa-leaf-heart:after,.fad.fa-leaf-heart:after{content:"\f4cb\f4cb"}.fa-duotone.fa-house-building:after,.fad.fa-house-building:after{content:"\e1b1\e1b1"}.fa-duotone.fa-cheese-swiss:after,.fad.fa-cheese-swiss:after{content:"\f7f0\f7f0"}.fa-duotone.fa-spoon:after,.fa-duotone.fa-utensil-spoon:after,.fad.fa-spoon:after,.fad.fa-utensil-spoon:after{content:"\f2e5\f2e5"}.fa-duotone.fa-jar-wheat:after,.fad.fa-jar-wheat:after{content:"\e517\e517"}.fa-duotone.fa-envelopes-bulk:after,.fa-duotone.fa-mail-bulk:after,.fad.fa-envelopes-bulk:after,.fad.fa-mail-bulk:after{content:"\f674\f674"}.fa-duotone.fa-file-circle-exclamation:after,.fad.fa-file-circle-exclamation:after{content:"\e4eb\e4eb"}.fa-duotone.fa-bow-arrow:after,.fad.fa-bow-arrow:after{content:"\f6b9\f6b9"}.fa-duotone.fa-cart-xmark:after,.fad.fa-cart-xmark:after{content:"\e0dd\e0dd"}.fa-duotone.fa-hexagon-xmark:after,.fa-duotone.fa-times-hexagon:after,.fa-duotone.fa-xmark-hexagon:after,.fad.fa-hexagon-xmark:after,.fad.fa-times-hexagon:after,.fad.fa-xmark-hexagon:after{content:"\f2ee\f2ee"}.fa-duotone.fa-circle-h:after,.fa-duotone.fa-hospital-symbol:after,.fad.fa-circle-h:after,.fad.fa-hospital-symbol:after{content:"\f47e\f47e"}.fa-duotone.fa-merge:after,.fad.fa-merge:after{content:"\e526\e526"}.fa-duotone.fa-pager:after,.fad.fa-pager:after{content:"\f815\f815"}.fa-duotone.fa-cart-minus:after,.fad.fa-cart-minus:after{content:"\e0db\e0db"}.fa-duotone.fa-address-book:after,.fa-duotone.fa-contact-book:after,.fad.fa-address-book:after,.fad.fa-contact-book:after{content:"\f2b9\f2b9"}.fa-duotone.fa-pan-frying:after,.fad.fa-pan-frying:after{content:"\e42c\e42c"}.fa-duotone.fa-grid-3:after,.fa-duotone.fa-grid:after,.fad.fa-grid-3:after,.fad.fa-grid:after{content:"\e195\e195"}.fa-duotone.fa-football-helmet:after,.fad.fa-football-helmet:after{content:"\f44f\f44f"}.fa-duotone.fa-hand-love:after,.fad.fa-hand-love:after{content:"\e1a5\e1a5"}.fa-duotone.fa-trees:after,.fad.fa-trees:after{content:"\f724\f724"}.fa-duotone.fa-strikethrough:after,.fad.fa-strikethrough:after{content:"\f0cc\f0cc"}.fa-duotone.fa-page:after,.fad.fa-page:after{content:"\e428\e428"}.fa-duotone.fa-k:after,.fad.fa-k:after{content:"\4b\4b"}.fa-duotone.fa-diagram-previous:after,.fad.fa-diagram-previous:after{content:"\e478\e478"}.fa-duotone.fa-gauge-min:after,.fa-duotone.fa-tachometer-alt-slowest:after,.fad.fa-gauge-min:after,.fad.fa-tachometer-alt-slowest:after{content:"\f628\f628"}.fa-duotone.fa-folder-grid:after,.fad.fa-folder-grid:after{content:"\e188\e188"}.fa-duotone.fa-eggplant:after,.fad.fa-eggplant:after{content:"\e16c\e16c"}.fa-duotone.fa-ram:after,.fad.fa-ram:after{content:"\f70a\f70a"}.fa-duotone.fa-landmark-flag:after,.fad.fa-landmark-flag:after{content:"\e51c\e51c"}.fa-duotone.fa-lips:after,.fad.fa-lips:after{content:"\f600\f600"}.fa-duotone.fa-pencil-alt:after,.fa-duotone.fa-pencil:after,.fad.fa-pencil-alt:after,.fad.fa-pencil:after{content:"\f303\f303"}.fa-duotone.fa-backward:after,.fad.fa-backward:after{content:"\f04a\f04a"}.fa-duotone.fa-caret-right:after,.fad.fa-caret-right:after{content:"\f0da\f0da"}.fa-duotone.fa-comments:after,.fad.fa-comments:after{content:"\f086\f086"}.fa-duotone.fa-file-clipboard:after,.fa-duotone.fa-paste:after,.fad.fa-file-clipboard:after,.fad.fa-paste:after{content:"\f0ea\f0ea"}.fa-duotone.fa-desktop-arrow-down:after,.fad.fa-desktop-arrow-down:after{content:"\e155\e155"}.fa-duotone.fa-code-pull-request:after,.fad.fa-code-pull-request:after{content:"\e13c\e13c"}.fa-duotone.fa-pumpkin:after,.fad.fa-pumpkin:after{content:"\f707\f707"}.fa-duotone.fa-clipboard-list:after,.fad.fa-clipboard-list:after{content:"\f46d\f46d"}.fa-duotone.fa-pen-field:after,.fad.fa-pen-field:after{content:"\e211\e211"}.fa-duotone.fa-blueberries:after,.fad.fa-blueberries:after{content:"\e2e8\e2e8"}.fa-duotone.fa-truck-loading:after,.fa-duotone.fa-truck-ramp-box:after,.fad.fa-truck-loading:after,.fad.fa-truck-ramp-box:after{content:"\f4de\f4de"}.fa-duotone.fa-note:after,.fad.fa-note:after{content:"\e1ff\e1ff"}.fa-duotone.fa-arrow-down-to-square:after,.fad.fa-arrow-down-to-square:after{content:"\e096\e096"}.fa-duotone.fa-user-check:after,.fad.fa-user-check:after{content:"\f4fc\f4fc"}.fa-duotone.fa-cloud-xmark:after,.fad.fa-cloud-xmark:after{content:"\e35f\e35f"}.fa-duotone.fa-vial-virus:after,.fad.fa-vial-virus:after{content:"\e597\e597"}.fa-duotone.fa-book-alt:after,.fa-duotone.fa-book-blank:after,.fad.fa-book-alt:after,.fad.fa-book-blank:after{content:"\f5d9\f5d9"}.fa-duotone.fa-golf-flag-hole:after,.fad.fa-golf-flag-hole:after{content:"\e3ac\e3ac"}.fa-duotone.fa-comment-alt-arrow-down:after,.fa-duotone.fa-message-arrow-down:after,.fad.fa-comment-alt-arrow-down:after,.fad.fa-message-arrow-down:after{content:"\e1db\e1db"}.fa-duotone.fa-face-unamused:after,.fad.fa-face-unamused:after{content:"\e39f\e39f"}.fa-duotone.fa-sheet-plastic:after,.fad.fa-sheet-plastic:after{content:"\e571\e571"}.fa-duotone.fa-circle-9:after,.fad.fa-circle-9:after{content:"\e0f6\e0f6"}.fa-duotone.fa-blog:after,.fad.fa-blog:after{content:"\f781\f781"}.fa-duotone.fa-user-ninja:after,.fad.fa-user-ninja:after{content:"\f504\f504"}.fa-duotone.fa-pencil-slash:after,.fad.fa-pencil-slash:after{content:"\e215\e215"}.fa-duotone.fa-bowling-pins:after,.fad.fa-bowling-pins:after{content:"\f437\f437"}.fa-duotone.fa-person-arrow-up-from-line:after,.fad.fa-person-arrow-up-from-line:after{content:"\e539\e539"}.fa-duotone.fa-down-right:after,.fad.fa-down-right:after{content:"\e16b\e16b"}.fa-duotone.fa-scroll-torah:after,.fa-duotone.fa-torah:after,.fad.fa-scroll-torah:after,.fad.fa-torah:after{content:"\f6a0\f6a0"}.fa-duotone.fa-webhook:after,.fad.fa-webhook:after{content:"\e5d5\e5d5"}.fa-duotone.fa-blinds-open:after,.fad.fa-blinds-open:after{content:"\f8fc\f8fc"}.fa-duotone.fa-fence:after,.fad.fa-fence:after{content:"\e303\e303"}.fa-duotone.fa-arrow-alt-up:after,.fa-duotone.fa-up:after,.fad.fa-arrow-alt-up:after,.fad.fa-up:after{content:"\f357\f357"}.fa-duotone.fa-broom-ball:after,.fa-duotone.fa-quidditch-broom-ball:after,.fa-duotone.fa-quidditch:after,.fad.fa-broom-ball:after,.fad.fa-quidditch-broom-ball:after,.fad.fa-quidditch:after{content:"\f458\f458"}.fa-duotone.fa-drumstick:after,.fad.fa-drumstick:after{content:"\f6d6\f6d6"}.fa-duotone.fa-square-v:after,.fad.fa-square-v:after{content:"\e284\e284"}.fa-duotone.fa-face-awesome:after,.fa-duotone.fa-gave-dandy:after,.fad.fa-face-awesome:after,.fad.fa-gave-dandy:after{content:"\e409\e409"}.fa-duotone.fa-dial-off:after,.fad.fa-dial-off:after{content:"\e162\e162"}.fa-duotone.fa-toggle-off:after,.fad.fa-toggle-off:after{content:"\f204\f204"}.fa-duotone.fa-face-smile-horns:after,.fad.fa-face-smile-horns:after{content:"\e391\e391"}.fa-duotone.fa-archive:after,.fa-duotone.fa-box-archive:after,.fad.fa-archive:after,.fad.fa-box-archive:after{content:"\f187\f187"}.fa-duotone.fa-grapes:after,.fad.fa-grapes:after{content:"\e306\e306"}.fa-duotone.fa-person-drowning:after,.fad.fa-person-drowning:after{content:"\e545\e545"}.fa-duotone.fa-dial-max:after,.fad.fa-dial-max:after{content:"\e15e\e15e"}.fa-duotone.fa-circle-m:after,.fad.fa-circle-m:after{content:"\e115\e115"}.fa-duotone.fa-calendar-image:after,.fad.fa-calendar-image:after{content:"\e0d4\e0d4"}.fa-duotone.fa-caret-circle-down:after,.fa-duotone.fa-circle-caret-down:after,.fad.fa-caret-circle-down:after,.fad.fa-circle-caret-down:after{content:"\f32d\f32d"}.fa-duotone.fa-arrow-down-9-1:after,.fa-duotone.fa-sort-numeric-desc:after,.fa-duotone.fa-sort-numeric-down-alt:after,.fad.fa-arrow-down-9-1:after,.fad.fa-sort-numeric-desc:after,.fad.fa-sort-numeric-down-alt:after{content:"\f886\f886"}.fa-duotone.fa-face-grin-tongue-squint:after,.fa-duotone.fa-grin-tongue-squint:after,.fad.fa-face-grin-tongue-squint:after,.fad.fa-grin-tongue-squint:after{content:"\f58a\f58a"}.fa-duotone.fa-shish-kebab:after,.fad.fa-shish-kebab:after{content:"\f821\f821"}.fa-duotone.fa-spray-can:after,.fad.fa-spray-can:after{content:"\f5bd\f5bd"}.fa-duotone.fa-alarm-snooze:after,.fad.fa-alarm-snooze:after{content:"\f845\f845"}.fa-duotone.fa-scarecrow:after,.fad.fa-scarecrow:after{content:"\f70d\f70d"}.fa-duotone.fa-truck-monster:after,.fad.fa-truck-monster:after{content:"\f63b\f63b"}.fa-duotone.fa-gift-card:after,.fad.fa-gift-card:after{content:"\f663\f663"}.fa-duotone.fa-w:after,.fad.fa-w:after{content:"\57\57"}.fa-duotone.fa-code-pull-request-draft:after,.fad.fa-code-pull-request-draft:after{content:"\e3fa\e3fa"}.fa-duotone.fa-square-b:after,.fad.fa-square-b:after{content:"\e264\e264"}.fa-duotone.fa-elephant:after,.fad.fa-elephant:after{content:"\f6da\f6da"}.fa-duotone.fa-earth-africa:after,.fa-duotone.fa-globe-africa:after,.fad.fa-earth-africa:after,.fad.fa-globe-africa:after{content:"\f57c\f57c"}.fa-duotone.fa-rainbow:after,.fad.fa-rainbow:after{content:"\f75b\f75b"}.fa-duotone.fa-circle-notch:after,.fad.fa-circle-notch:after{content:"\f1ce\f1ce"}.fa-duotone.fa-tablet-alt:after,.fa-duotone.fa-tablet-screen-button:after,.fad.fa-tablet-alt:after,.fad.fa-tablet-screen-button:after{content:"\f3fa\f3fa"}.fa-duotone.fa-paw:after,.fad.fa-paw:after{content:"\f1b0\f1b0"}.fa-duotone.fa-message-question:after,.fad.fa-message-question:after{content:"\e1e3\e1e3"}.fa-duotone.fa-cloud:after,.fad.fa-cloud:after{content:"\f0c2\f0c2"}.fa-duotone.fa-trowel-bricks:after,.fad.fa-trowel-bricks:after{content:"\e58a\e58a"}.fa-duotone.fa-square-3:after,.fad.fa-square-3:after{content:"\e258\e258"}.fa-duotone.fa-face-flushed:after,.fa-duotone.fa-flushed:after,.fad.fa-face-flushed:after,.fad.fa-flushed:after{content:"\f579\f579"}.fa-duotone.fa-hospital-user:after,.fad.fa-hospital-user:after{content:"\f80d\f80d"}.fa-duotone.fa-microwave:after,.fad.fa-microwave:after{content:"\e01b\e01b"}.fa-duotone.fa-chf-sign:after,.fad.fa-chf-sign:after{content:"\e602\e602"}.fa-duotone.fa-tent-arrow-left-right:after,.fad.fa-tent-arrow-left-right:after{content:"\e57f\e57f"}.fa-duotone.fa-cart-circle-arrow-up:after,.fad.fa-cart-circle-arrow-up:after{content:"\e3f0\e3f0"}.fa-duotone.fa-trash-clock:after,.fad.fa-trash-clock:after{content:"\e2b0\e2b0"}.fa-duotone.fa-gavel:after,.fa-duotone.fa-legal:after,.fad.fa-gavel:after,.fad.fa-legal:after{content:"\f0e3\f0e3"}.fa-duotone.fa-sprinkler-ceiling:after,.fad.fa-sprinkler-ceiling:after{content:"\e44c\e44c"}.fa-duotone.fa-browsers:after,.fad.fa-browsers:after{content:"\e0cb\e0cb"}.fa-duotone.fa-trillium:after,.fad.fa-trillium:after{content:"\e588\e588"}.fa-duotone.fa-music-slash:after,.fad.fa-music-slash:after{content:"\f8d1\f8d1"}.fa-duotone.fa-truck-ramp:after,.fad.fa-truck-ramp:after{content:"\f4e0\f4e0"}.fa-duotone.fa-binoculars:after,.fad.fa-binoculars:after{content:"\f1e5\f1e5"}.fa-duotone.fa-microphone-slash:after,.fad.fa-microphone-slash:after{content:"\f131\f131"}.fa-duotone.fa-box-tissue:after,.fad.fa-box-tissue:after{content:"\e05b\e05b"}.fa-duotone.fa-circle-c:after,.fad.fa-circle-c:after{content:"\e101\e101"}.fa-duotone.fa-star-christmas:after,.fad.fa-star-christmas:after{content:"\f7d4\f7d4"}.fa-duotone.fa-chart-bullet:after,.fad.fa-chart-bullet:after{content:"\e0e1\e0e1"}.fa-duotone.fa-motorcycle:after,.fad.fa-motorcycle:after{content:"\f21c\f21c"}.fa-duotone.fa-tree-christmas:after,.fad.fa-tree-christmas:after{content:"\f7db\f7db"}.fa-duotone.fa-tire-flat:after,.fad.fa-tire-flat:after{content:"\f632\f632"}.fa-duotone.fa-sunglasses:after,.fad.fa-sunglasses:after{content:"\f892\f892"}.fa-duotone.fa-badge:after,.fad.fa-badge:after{content:"\f335\f335"}.fa-duotone.fa-comment-alt-edit:after,.fa-duotone.fa-message-edit:after,.fa-duotone.fa-message-pen:after,.fad.fa-comment-alt-edit:after,.fad.fa-message-edit:after,.fad.fa-message-pen:after{content:"\f4a4\f4a4"}.fa-duotone.fa-bell-concierge:after,.fa-duotone.fa-concierge-bell:after,.fad.fa-bell-concierge:after,.fad.fa-concierge-bell:after{content:"\f562\f562"}.fa-duotone.fa-pen-ruler:after,.fa-duotone.fa-pencil-ruler:after,.fad.fa-pen-ruler:after,.fad.fa-pencil-ruler:after{content:"\f5ae\f5ae"}.fa-duotone.fa-arrow-progress:after,.fad.fa-arrow-progress:after{content:"\e5df\e5df"}.fa-duotone.fa-chess-rook-alt:after,.fa-duotone.fa-chess-rook-piece:after,.fad.fa-chess-rook-alt:after,.fad.fa-chess-rook-piece:after{content:"\f448\f448"}.fa-duotone.fa-square-root:after,.fad.fa-square-root:after{content:"\f697\f697"}.fa-duotone.fa-album-collection-circle-plus:after,.fad.fa-album-collection-circle-plus:after{content:"\e48e\e48e"}.fa-duotone.fa-people-arrows-left-right:after,.fa-duotone.fa-people-arrows:after,.fad.fa-people-arrows-left-right:after,.fad.fa-people-arrows:after{content:"\e068\e068"}.fa-duotone.fa-face-angry-horns:after,.fad.fa-face-angry-horns:after{content:"\e368\e368"}.fa-duotone.fa-mars-and-venus-burst:after,.fad.fa-mars-and-venus-burst:after{content:"\e523\e523"}.fa-duotone.fa-tombstone:after,.fad.fa-tombstone:after{content:"\f720\f720"}.fa-duotone.fa-caret-square-right:after,.fa-duotone.fa-square-caret-right:after,.fad.fa-caret-square-right:after,.fad.fa-square-caret-right:after{content:"\f152\f152"}.fa-duotone.fa-cut:after,.fa-duotone.fa-scissors:after,.fad.fa-cut:after,.fad.fa-scissors:after{content:"\f0c4\f0c4"}.fa-duotone.fa-list-music:after,.fad.fa-list-music:after{content:"\f8c9\f8c9"}.fa-duotone.fa-sun-plant-wilt:after,.fad.fa-sun-plant-wilt:after{content:"\e57a\e57a"}.fa-duotone.fa-toilets-portable:after,.fad.fa-toilets-portable:after{content:"\e584\e584"}.fa-duotone.fa-hockey-puck:after,.fad.fa-hockey-puck:after{content:"\f453\f453"}.fa-duotone.fa-mustache:after,.fad.fa-mustache:after{content:"\e5bc\e5bc"}.fa-duotone.fa-hyphen:after,.fad.fa-hyphen:after{content:"\2d\2d"}.fa-duotone.fa-table:after,.fad.fa-table:after{content:"\f0ce\f0ce"}.fa-duotone.fa-user-chef:after,.fad.fa-user-chef:after{content:"\e3d2\e3d2"}.fa-duotone.fa-comment-alt-image:after,.fa-duotone.fa-message-image:after,.fad.fa-comment-alt-image:after,.fad.fa-message-image:after{content:"\e1e0\e1e0"}.fa-duotone.fa-users-medical:after,.fad.fa-users-medical:after{content:"\f830\f830"}.fa-duotone.fa-sensor-alert:after,.fa-duotone.fa-sensor-triangle-exclamation:after,.fad.fa-sensor-alert:after,.fad.fa-sensor-triangle-exclamation:after{content:"\e029\e029"}.fa-duotone.fa-magnifying-glass-arrow-right:after,.fad.fa-magnifying-glass-arrow-right:after{content:"\e521\e521"}.fa-duotone.fa-digital-tachograph:after,.fa-duotone.fa-tachograph-digital:after,.fad.fa-digital-tachograph:after,.fad.fa-tachograph-digital:after{content:"\f566\f566"}.fa-duotone.fa-face-mask:after,.fad.fa-face-mask:after{content:"\e37f\e37f"}.fa-duotone.fa-pickleball:after,.fad.fa-pickleball:after{content:"\e435\e435"}.fa-duotone.fa-star-sharp-half:after,.fad.fa-star-sharp-half:after{content:"\e28c\e28c"}.fa-duotone.fa-users-slash:after,.fad.fa-users-slash:after{content:"\e073\e073"}.fa-duotone.fa-clover:after,.fad.fa-clover:after{content:"\e139\e139"}.fa-duotone.fa-meat:after,.fad.fa-meat:after{content:"\f814\f814"}.fa-duotone.fa-mail-reply:after,.fa-duotone.fa-reply:after,.fad.fa-mail-reply:after,.fad.fa-reply:after{content:"\f3e5\f3e5"}.fa-duotone.fa-star-and-crescent:after,.fad.fa-star-and-crescent:after{content:"\f699\f699"}.fa-duotone.fa-empty-set:after,.fad.fa-empty-set:after{content:"\f656\f656"}.fa-duotone.fa-house-fire:after,.fad.fa-house-fire:after{content:"\e50c\e50c"}.fa-duotone.fa-minus-square:after,.fa-duotone.fa-square-minus:after,.fad.fa-minus-square:after,.fad.fa-square-minus:after{content:"\f146\f146"}.fa-duotone.fa-helicopter:after,.fad.fa-helicopter:after{content:"\f533\f533"}.fa-duotone.fa-bird:after,.fad.fa-bird:after{content:"\e469\e469"}.fa-duotone.fa-compass:after,.fad.fa-compass:after{content:"\f14e\f14e"}.fa-duotone.fa-caret-square-down:after,.fa-duotone.fa-square-caret-down:after,.fad.fa-caret-square-down:after,.fad.fa-square-caret-down:after{content:"\f150\f150"}.fa-duotone.fa-heart-half-alt:after,.fa-duotone.fa-heart-half-stroke:after,.fad.fa-heart-half-alt:after,.fad.fa-heart-half-stroke:after{content:"\e1ac\e1ac"}.fa-duotone.fa-file-circle-question:after,.fad.fa-file-circle-question:after{content:"\e4ef\e4ef"}.fa-duotone.fa-laptop-code:after,.fad.fa-laptop-code:after{content:"\f5fc\f5fc"}.fa-duotone.fa-joystick:after,.fad.fa-joystick:after{content:"\f8c5\f8c5"}.fa-duotone.fa-grill-fire:after,.fad.fa-grill-fire:after{content:"\e5a4\e5a4"}.fa-duotone.fa-rectangle-vertical-history:after,.fad.fa-rectangle-vertical-history:after{content:"\e237\e237"}.fa-duotone.fa-swatchbook:after,.fad.fa-swatchbook:after{content:"\f5c3\f5c3"}.fa-duotone.fa-prescription-bottle:after,.fad.fa-prescription-bottle:after{content:"\f485\f485"}.fa-duotone.fa-bars:after,.fa-duotone.fa-navicon:after,.fad.fa-bars:after,.fad.fa-navicon:after{content:"\f0c9\f0c9"}.fa-duotone.fa-keyboard-left:after,.fad.fa-keyboard-left:after{content:"\e1c3\e1c3"}.fa-duotone.fa-people-group:after,.fad.fa-people-group:after{content:"\e533\e533"}.fa-duotone.fa-hourglass-3:after,.fa-duotone.fa-hourglass-end:after,.fad.fa-hourglass-3:after,.fad.fa-hourglass-end:after{content:"\f253\f253"}.fa-duotone.fa-heart-broken:after,.fa-duotone.fa-heart-crack:after,.fad.fa-heart-broken:after,.fad.fa-heart-crack:after{content:"\f7a9\f7a9"}.fa-duotone.fa-face-beam-hand-over-mouth:after,.fad.fa-face-beam-hand-over-mouth:after{content:"\e47c\e47c"}.fa-duotone.fa-droplet-percent:after,.fa-duotone.fa-humidity:after,.fad.fa-droplet-percent:after,.fad.fa-humidity:after{content:"\f750\f750"}.fa-duotone.fa-external-link-square-alt:after,.fa-duotone.fa-square-up-right:after,.fad.fa-external-link-square-alt:after,.fad.fa-square-up-right:after{content:"\f360\f360"}.fa-duotone.fa-face-kiss-beam:after,.fa-duotone.fa-kiss-beam:after,.fad.fa-face-kiss-beam:after,.fad.fa-kiss-beam:after{content:"\f597\f597"}.fa-duotone.fa-corn:after,.fad.fa-corn:after{content:"\f6c7\f6c7"}.fa-duotone.fa-roller-coaster:after,.fad.fa-roller-coaster:after{content:"\e324\e324"}.fa-duotone.fa-photo-film-music:after,.fad.fa-photo-film-music:after{content:"\e228\e228"}.fa-duotone.fa-radar:after,.fad.fa-radar:after{content:"\e024\e024"}.fa-duotone.fa-sickle:after,.fad.fa-sickle:after{content:"\f822\f822"}.fa-duotone.fa-film:after,.fad.fa-film:after{content:"\f008\f008"}.fa-duotone.fa-coconut:after,.fad.fa-coconut:after{content:"\e2f6\e2f6"}.fa-duotone.fa-ruler-horizontal:after,.fad.fa-ruler-horizontal:after{content:"\f547\f547"}.fa-duotone.fa-shield-cross:after,.fad.fa-shield-cross:after{content:"\f712\f712"}.fa-duotone.fa-cassette-tape:after,.fad.fa-cassette-tape:after{content:"\f8ab\f8ab"}.fa-duotone.fa-square-terminal:after,.fad.fa-square-terminal:after{content:"\e32a\e32a"}.fa-duotone.fa-people-robbery:after,.fad.fa-people-robbery:after{content:"\e536\e536"}.fa-duotone.fa-lightbulb:after,.fad.fa-lightbulb:after{content:"\f0eb\f0eb"}.fa-duotone.fa-caret-left:after,.fad.fa-caret-left:after{content:"\f0d9\f0d9"}.fa-duotone.fa-comment-middle:after,.fad.fa-comment-middle:after{content:"\e149\e149"}.fa-duotone.fa-trash-can-list:after,.fad.fa-trash-can-list:after{content:"\e2ab\e2ab"}.fa-duotone.fa-block:after,.fad.fa-block:after{content:"\e46a\e46a"}.fa-duotone.fa-circle-exclamation:after,.fa-duotone.fa-exclamation-circle:after,.fad.fa-circle-exclamation:after,.fad.fa-exclamation-circle:after{content:"\f06a\f06a"}.fa-duotone.fa-school-circle-xmark:after,.fad.fa-school-circle-xmark:after{content:"\e56d\e56d"}.fa-duotone.fa-arrow-right-from-bracket:after,.fa-duotone.fa-sign-out:after,.fad.fa-arrow-right-from-bracket:after,.fad.fa-sign-out:after{content:"\f08b\f08b"}.fa-duotone.fa-face-frown-slight:after,.fad.fa-face-frown-slight:after{content:"\e376\e376"}.fa-duotone.fa-chevron-circle-down:after,.fa-duotone.fa-circle-chevron-down:after,.fad.fa-chevron-circle-down:after,.fad.fa-circle-chevron-down:after{content:"\f13a\f13a"}.fa-duotone.fa-sidebar-flip:after,.fad.fa-sidebar-flip:after{content:"\e24f\e24f"}.fa-duotone.fa-unlock-alt:after,.fa-duotone.fa-unlock-keyhole:after,.fad.fa-unlock-alt:after,.fad.fa-unlock-keyhole:after{content:"\f13e\f13e"}.fa-duotone.fa-temperature-list:after,.fad.fa-temperature-list:after{content:"\e299\e299"}.fa-duotone.fa-cloud-showers-heavy:after,.fad.fa-cloud-showers-heavy:after{content:"\f740\f740"}.fa-duotone.fa-headphones-alt:after,.fa-duotone.fa-headphones-simple:after,.fad.fa-headphones-alt:after,.fad.fa-headphones-simple:after{content:"\f58f\f58f"}.fa-duotone.fa-sitemap:after,.fad.fa-sitemap:after{content:"\f0e8\f0e8"}.fa-duotone.fa-pipe-section:after,.fad.fa-pipe-section:after{content:"\e438\e438"}.fa-duotone.fa-space-station-moon-alt:after,.fa-duotone.fa-space-station-moon-construction:after,.fad.fa-space-station-moon-alt:after,.fad.fa-space-station-moon-construction:after{content:"\e034\e034"}.fa-duotone.fa-circle-dollar-to-slot:after,.fa-duotone.fa-donate:after,.fad.fa-circle-dollar-to-slot:after,.fad.fa-donate:after{content:"\f4b9\f4b9"}.fa-duotone.fa-memory:after,.fad.fa-memory:after{content:"\f538\f538"}.fa-duotone.fa-face-sleeping:after,.fad.fa-face-sleeping:after{content:"\e38d\e38d"}.fa-duotone.fa-road-spikes:after,.fad.fa-road-spikes:after{content:"\e568\e568"}.fa-duotone.fa-fire-burner:after,.fad.fa-fire-burner:after{content:"\e4f1\e4f1"}.fa-duotone.fa-squirrel:after,.fad.fa-squirrel:after{content:"\f71a\f71a"}.fa-duotone.fa-arrow-to-top:after,.fa-duotone.fa-arrow-up-to-line:after,.fad.fa-arrow-to-top:after,.fad.fa-arrow-up-to-line:after{content:"\f341\f341"}.fa-duotone.fa-flag:after,.fad.fa-flag:after{content:"\f024\f024"}.fa-duotone.fa-face-cowboy-hat:after,.fad.fa-face-cowboy-hat:after{content:"\e36e\e36e"}.fa-duotone.fa-hanukiah:after,.fad.fa-hanukiah:after{content:"\f6e6\f6e6"}.fa-duotone.fa-chart-scatter-3d:after,.fad.fa-chart-scatter-3d:after{content:"\e0e8\e0e8"}.fa-duotone.fa-display-chart-up:after,.fad.fa-display-chart-up:after{content:"\e5e3\e5e3"}.fa-duotone.fa-square-code:after,.fad.fa-square-code:after{content:"\e267\e267"}.fa-duotone.fa-feather:after,.fad.fa-feather:after{content:"\f52d\f52d"}.fa-duotone.fa-volume-down:after,.fa-duotone.fa-volume-low:after,.fad.fa-volume-down:after,.fad.fa-volume-low:after{content:"\f027\f027"}.fa-duotone.fa-times-to-slot:after,.fa-duotone.fa-vote-nay:after,.fa-duotone.fa-xmark-to-slot:after,.fad.fa-times-to-slot:after,.fad.fa-vote-nay:after,.fad.fa-xmark-to-slot:after{content:"\f771\f771"}.fa-duotone.fa-box-alt:after,.fa-duotone.fa-box-taped:after,.fad.fa-box-alt:after,.fad.fa-box-taped:after{content:"\f49a\f49a"}.fa-duotone.fa-comment-slash:after,.fad.fa-comment-slash:after{content:"\f4b3\f4b3"}.fa-duotone.fa-swords:after,.fad.fa-swords:after{content:"\f71d\f71d"}.fa-duotone.fa-cloud-sun-rain:after,.fad.fa-cloud-sun-rain:after{content:"\f743\f743"}.fa-duotone.fa-album:after,.fad.fa-album:after{content:"\f89f\f89f"}.fa-duotone.fa-circle-n:after,.fad.fa-circle-n:after{content:"\e118\e118"}.fa-duotone.fa-compress:after,.fad.fa-compress:after{content:"\f066\f066"}.fa-duotone.fa-wheat-alt:after,.fa-duotone.fa-wheat-awn:after,.fad.fa-wheat-alt:after,.fad.fa-wheat-awn:after{content:"\e2cd\e2cd"}.fa-duotone.fa-ankh:after,.fad.fa-ankh:after{content:"\f644\f644"}.fa-duotone.fa-hands-holding-child:after,.fad.fa-hands-holding-child:after{content:"\e4fa\e4fa"}.fa-duotone.fa-asterisk:after,.fad.fa-asterisk:after{content:"\2a\2a"}.fa-duotone.fa-key-skeleton-left-right:after,.fad.fa-key-skeleton-left-right:after{content:"\e3b4\e3b4"}.fa-duotone.fa-comment-lines:after,.fad.fa-comment-lines:after{content:"\f4b0\f4b0"}.fa-duotone.fa-luchador-mask:after,.fa-duotone.fa-luchador:after,.fa-duotone.fa-mask-luchador:after,.fad.fa-luchador-mask:after,.fad.fa-luchador:after,.fad.fa-mask-luchador:after{content:"\f455\f455"}.fa-duotone.fa-check-square:after,.fa-duotone.fa-square-check:after,.fad.fa-check-square:after,.fad.fa-square-check:after{content:"\f14a\f14a"}.fa-duotone.fa-shredder:after,.fad.fa-shredder:after{content:"\f68a\f68a"}.fa-duotone.fa-book-open-alt:after,.fa-duotone.fa-book-open-cover:after,.fad.fa-book-open-alt:after,.fad.fa-book-open-cover:after{content:"\e0c0\e0c0"}.fa-duotone.fa-sandwich:after,.fad.fa-sandwich:after{content:"\f81f\f81f"}.fa-duotone.fa-peseta-sign:after,.fad.fa-peseta-sign:after{content:"\e221\e221"}.fa-duotone.fa-parking-slash:after,.fa-duotone.fa-square-parking-slash:after,.fad.fa-parking-slash:after,.fad.fa-square-parking-slash:after{content:"\f617\f617"}.fa-duotone.fa-train-tunnel:after,.fad.fa-train-tunnel:after{content:"\e454\e454"}.fa-duotone.fa-header:after,.fa-duotone.fa-heading:after,.fad.fa-header:after,.fad.fa-heading:after{content:"\f1dc\f1dc"}.fa-duotone.fa-ghost:after,.fad.fa-ghost:after{content:"\f6e2\f6e2"}.fa-duotone.fa-face-anguished:after,.fad.fa-face-anguished:after{content:"\e369\e369"}.fa-duotone.fa-hockey-sticks:after,.fad.fa-hockey-sticks:after{content:"\f454\f454"}.fa-duotone.fa-abacus:after,.fad.fa-abacus:after{content:"\f640\f640"}.fa-duotone.fa-film-alt:after,.fa-duotone.fa-film-simple:after,.fad.fa-film-alt:after,.fad.fa-film-simple:after{content:"\f3a0\f3a0"}.fa-duotone.fa-list-squares:after,.fa-duotone.fa-list:after,.fad.fa-list-squares:after,.fad.fa-list:after{content:"\f03a\f03a"}.fa-duotone.fa-tree-palm:after,.fad.fa-tree-palm:after{content:"\f82b\f82b"}.fa-duotone.fa-phone-square-alt:after,.fa-duotone.fa-square-phone-flip:after,.fad.fa-phone-square-alt:after,.fad.fa-square-phone-flip:after{content:"\f87b\f87b"}.fa-duotone.fa-cart-plus:after,.fad.fa-cart-plus:after{content:"\f217\f217"}.fa-duotone.fa-gamepad:after,.fad.fa-gamepad:after{content:"\f11b\f11b"}.fa-duotone.fa-border-center-v:after,.fad.fa-border-center-v:after{content:"\f89d\f89d"}.fa-duotone.fa-circle-dot:after,.fa-duotone.fa-dot-circle:after,.fad.fa-circle-dot:after,.fad.fa-dot-circle:after{content:"\f192\f192"}.fa-duotone.fa-clipboard-medical:after,.fad.fa-clipboard-medical:after{content:"\e133\e133"}.fa-duotone.fa-dizzy:after,.fa-duotone.fa-face-dizzy:after,.fad.fa-dizzy:after,.fad.fa-face-dizzy:after{content:"\f567\f567"}.fa-duotone.fa-egg:after,.fad.fa-egg:after{content:"\f7fb\f7fb"}.fa-duotone.fa-arrow-alt-to-top:after,.fa-duotone.fa-up-to-line:after,.fad.fa-arrow-alt-to-top:after,.fad.fa-up-to-line:after{content:"\f34d\f34d"}.fa-duotone.fa-house-medical-circle-xmark:after,.fad.fa-house-medical-circle-xmark:after{content:"\e513\e513"}.fa-duotone.fa-watch-fitness:after,.fad.fa-watch-fitness:after{content:"\f63e\f63e"}.fa-duotone.fa-clock-nine-thirty:after,.fad.fa-clock-nine-thirty:after{content:"\e34d\e34d"}.fa-duotone.fa-campground:after,.fad.fa-campground:after{content:"\f6bb\f6bb"}.fa-duotone.fa-folder-plus:after,.fad.fa-folder-plus:after{content:"\f65e\f65e"}.fa-duotone.fa-jug:after,.fad.fa-jug:after{content:"\f8c6\f8c6"}.fa-duotone.fa-futbol-ball:after,.fa-duotone.fa-futbol:after,.fa-duotone.fa-soccer-ball:after,.fad.fa-futbol-ball:after,.fad.fa-futbol:after,.fad.fa-soccer-ball:after{content:"\f1e3\f1e3"}.fa-duotone.fa-snow-blowing:after,.fad.fa-snow-blowing:after{content:"\f761\f761"}.fa-duotone.fa-paint-brush:after,.fa-duotone.fa-paintbrush:after,.fad.fa-paint-brush:after,.fad.fa-paintbrush:after{content:"\f1fc\f1fc"}.fa-duotone.fa-lock:after,.fad.fa-lock:after{content:"\f023\f023"}.fa-duotone.fa-arrow-down-from-line:after,.fa-duotone.fa-arrow-from-top:after,.fad.fa-arrow-down-from-line:after,.fad.fa-arrow-from-top:after{content:"\f345\f345"}.fa-duotone.fa-gas-pump:after,.fad.fa-gas-pump:after{content:"\f52f\f52f"}.fa-duotone.fa-signal-alt-slash:after,.fa-duotone.fa-signal-bars-slash:after,.fad.fa-signal-alt-slash:after,.fad.fa-signal-bars-slash:after{content:"\f694\f694"}.fa-duotone.fa-monkey:after,.fad.fa-monkey:after{content:"\f6fb\f6fb"}.fa-duotone.fa-pro:after,.fa-duotone.fa-rectangle-pro:after,.fad.fa-pro:after,.fad.fa-rectangle-pro:after{content:"\e235\e235"}.fa-duotone.fa-house-night:after,.fad.fa-house-night:after{content:"\e010\e010"}.fa-duotone.fa-hot-tub-person:after,.fa-duotone.fa-hot-tub:after,.fad.fa-hot-tub-person:after,.fad.fa-hot-tub:after{content:"\f593\f593"}.fa-duotone.fa-globe-pointer:after,.fad.fa-globe-pointer:after{content:"\e60e\e60e"}.fa-duotone.fa-blanket:after,.fad.fa-blanket:after{content:"\f498\f498"}.fa-duotone.fa-map-location:after,.fa-duotone.fa-map-marked:after,.fad.fa-map-location:after,.fad.fa-map-marked:after{content:"\f59f\f59f"}.fa-duotone.fa-house-flood-water:after,.fad.fa-house-flood-water:after{content:"\e50e\e50e"}.fa-duotone.fa-comments-question-check:after,.fad.fa-comments-question-check:after{content:"\e14f\e14f"}.fa-duotone.fa-tree:after,.fad.fa-tree:after{content:"\f1bb\f1bb"}.fa-duotone.fa-arrows-cross:after,.fad.fa-arrows-cross:after{content:"\e0a2\e0a2"}.fa-duotone.fa-backpack:after,.fad.fa-backpack:after{content:"\f5d4\f5d4"}.fa-duotone.fa-square-small:after,.fad.fa-square-small:after{content:"\e27e\e27e"}.fa-duotone.fa-folder-arrow-up:after,.fa-duotone.fa-folder-upload:after,.fad.fa-folder-arrow-up:after,.fad.fa-folder-upload:after{content:"\e054\e054"}.fa-duotone.fa-bridge-lock:after,.fad.fa-bridge-lock:after{content:"\e4cc\e4cc"}.fa-duotone.fa-crosshairs-simple:after,.fad.fa-crosshairs-simple:after{content:"\e59f\e59f"}.fa-duotone.fa-sack-dollar:after,.fad.fa-sack-dollar:after{content:"\f81d\f81d"}.fa-duotone.fa-edit:after,.fa-duotone.fa-pen-to-square:after,.fad.fa-edit:after,.fad.fa-pen-to-square:after{content:"\f044\f044"}.fa-duotone.fa-sliders-h-square:after,.fa-duotone.fa-square-sliders:after,.fad.fa-sliders-h-square:after,.fad.fa-square-sliders:after{content:"\f3f0\f3f0"}.fa-duotone.fa-car-side:after,.fad.fa-car-side:after{content:"\f5e4\f5e4"}.fa-duotone.fa-comment-middle-top-alt:after,.fa-duotone.fa-message-middle-top:after,.fad.fa-comment-middle-top-alt:after,.fad.fa-message-middle-top:after{content:"\e1e2\e1e2"}.fa-duotone.fa-lightbulb-on:after,.fad.fa-lightbulb-on:after{content:"\f672\f672"}.fa-duotone.fa-knife:after,.fa-duotone.fa-utensil-knife:after,.fad.fa-knife:after,.fad.fa-utensil-knife:after{content:"\f2e4\f2e4"}.fa-duotone.fa-share-alt:after,.fa-duotone.fa-share-nodes:after,.fad.fa-share-alt:after,.fad.fa-share-nodes:after{content:"\f1e0\f1e0"}.fa-duotone.fa-display-chart-up-circle-dollar:after,.fad.fa-display-chart-up-circle-dollar:after{content:"\e5e6\e5e6"}.fa-duotone.fa-wave-sine:after,.fad.fa-wave-sine:after{content:"\f899\f899"}.fa-duotone.fa-heart-circle-minus:after,.fad.fa-heart-circle-minus:after{content:"\e4ff\e4ff"}.fa-duotone.fa-circle-w:after,.fad.fa-circle-w:after{content:"\e12c\e12c"}.fa-duotone.fa-calendar-circle:after,.fa-duotone.fa-circle-calendar:after,.fad.fa-calendar-circle:after,.fad.fa-circle-calendar:after{content:"\e102\e102"}.fa-duotone.fa-hourglass-2:after,.fa-duotone.fa-hourglass-half:after,.fad.fa-hourglass-2:after,.fad.fa-hourglass-half:after{content:"\f252\f252"}.fa-duotone.fa-microscope:after,.fad.fa-microscope:after{content:"\f610\f610"}.fa-duotone.fa-sunset:after,.fad.fa-sunset:after{content:"\f767\f767"}.fa-duotone.fa-sink:after,.fad.fa-sink:after{content:"\e06d\e06d"}.fa-duotone.fa-calendar-exclamation:after,.fad.fa-calendar-exclamation:after{content:"\f334\f334"}.fa-duotone.fa-truck-container-empty:after,.fad.fa-truck-container-empty:after{content:"\e2b5\e2b5"}.fa-duotone.fa-hand-heart:after,.fad.fa-hand-heart:after{content:"\f4bc\f4bc"}.fa-duotone.fa-bag-shopping:after,.fa-duotone.fa-shopping-bag:after,.fad.fa-bag-shopping:after,.fad.fa-shopping-bag:after{content:"\f290\f290"}.fa-duotone.fa-arrow-down-z-a:after,.fa-duotone.fa-sort-alpha-desc:after,.fa-duotone.fa-sort-alpha-down-alt:after,.fad.fa-arrow-down-z-a:after,.fad.fa-sort-alpha-desc:after,.fad.fa-sort-alpha-down-alt:after{content:"\f881\f881"}.fa-duotone.fa-mitten:after,.fad.fa-mitten:after{content:"\f7b5\f7b5"}.fa-duotone.fa-reply-clock:after,.fa-duotone.fa-reply-time:after,.fad.fa-reply-clock:after,.fad.fa-reply-time:after{content:"\e239\e239"}.fa-duotone.fa-person-rays:after,.fad.fa-person-rays:after{content:"\e54d\e54d"}.fa-duotone.fa-arrow-alt-right:after,.fa-duotone.fa-right:after,.fad.fa-arrow-alt-right:after,.fad.fa-right:after{content:"\f356\f356"}.fa-duotone.fa-circle-f:after,.fad.fa-circle-f:after{content:"\e10e\e10e"}.fa-duotone.fa-users:after,.fad.fa-users:after{content:"\f0c0\f0c0"}.fa-duotone.fa-face-pleading:after,.fad.fa-face-pleading:after{content:"\e386\e386"}.fa-duotone.fa-eye-slash:after,.fad.fa-eye-slash:after{content:"\f070\f070"}.fa-duotone.fa-flask-vial:after,.fad.fa-flask-vial:after{content:"\e4f3\e4f3"}.fa-duotone.fa-police-box:after,.fad.fa-police-box:after{content:"\e021\e021"}.fa-duotone.fa-cucumber:after,.fad.fa-cucumber:after{content:"\e401\e401"}.fa-duotone.fa-head-side-brain:after,.fad.fa-head-side-brain:after{content:"\f808\f808"}.fa-duotone.fa-hand-paper:after,.fa-duotone.fa-hand:after,.fad.fa-hand-paper:after,.fad.fa-hand:after{content:"\f256\f256"}.fa-duotone.fa-biking-mountain:after,.fa-duotone.fa-person-biking-mountain:after,.fad.fa-biking-mountain:after,.fad.fa-person-biking-mountain:after{content:"\f84b\f84b"}.fa-duotone.fa-utensils-slash:after,.fad.fa-utensils-slash:after{content:"\e464\e464"}.fa-duotone.fa-print-magnifying-glass:after,.fa-duotone.fa-print-search:after,.fad.fa-print-magnifying-glass:after,.fad.fa-print-search:after{content:"\f81a\f81a"}.fa-duotone.fa-folder-bookmark:after,.fad.fa-folder-bookmark:after{content:"\e186\e186"}.fa-duotone.fa-om:after,.fad.fa-om:after{content:"\f679\f679"}.fa-duotone.fa-pi:after,.fad.fa-pi:after{content:"\f67e\f67e"}.fa-duotone.fa-flask-potion:after,.fa-duotone.fa-flask-round-potion:after,.fad.fa-flask-potion:after,.fad.fa-flask-round-potion:after{content:"\f6e1\f6e1"}.fa-duotone.fa-face-shush:after,.fad.fa-face-shush:after{content:"\e38c\e38c"}.fa-duotone.fa-worm:after,.fad.fa-worm:after{content:"\e599\e599"}.fa-duotone.fa-house-circle-xmark:after,.fad.fa-house-circle-xmark:after{content:"\e50b\e50b"}.fa-duotone.fa-plug:after,.fad.fa-plug:after{content:"\f1e6\f1e6"}.fa-duotone.fa-calendar-circle-exclamation:after,.fad.fa-calendar-circle-exclamation:after{content:"\e46e\e46e"}.fa-duotone.fa-square-i:after,.fad.fa-square-i:after{content:"\e272\e272"}.fa-duotone.fa-chevron-up:after,.fad.fa-chevron-up:after{content:"\f077\f077"}.fa-duotone.fa-face-saluting:after,.fad.fa-face-saluting:after{content:"\e484\e484"}.fa-duotone.fa-gauge-simple-low:after,.fa-duotone.fa-tachometer-slow:after,.fad.fa-gauge-simple-low:after,.fad.fa-tachometer-slow:after{content:"\f62c\f62c"}.fa-duotone.fa-face-persevering:after,.fad.fa-face-persevering:after{content:"\e385\e385"}.fa-duotone.fa-camera-circle:after,.fa-duotone.fa-circle-camera:after,.fad.fa-camera-circle:after,.fad.fa-circle-camera:after{content:"\e103\e103"}.fa-duotone.fa-hand-spock:after,.fad.fa-hand-spock:after{content:"\f259\f259"}.fa-duotone.fa-spider-web:after,.fad.fa-spider-web:after{content:"\f719\f719"}.fa-duotone.fa-circle-microphone:after,.fa-duotone.fa-microphone-circle:after,.fad.fa-circle-microphone:after,.fad.fa-microphone-circle:after{content:"\e116\e116"}.fa-duotone.fa-book-arrow-up:after,.fad.fa-book-arrow-up:after{content:"\e0ba\e0ba"}.fa-duotone.fa-popsicle:after,.fad.fa-popsicle:after{content:"\e43e\e43e"}.fa-duotone.fa-command:after,.fad.fa-command:after{content:"\e142\e142"}.fa-duotone.fa-blinds:after,.fad.fa-blinds:after{content:"\f8fb\f8fb"}.fa-duotone.fa-stopwatch:after,.fad.fa-stopwatch:after{content:"\f2f2\f2f2"}.fa-duotone.fa-saxophone:after,.fad.fa-saxophone:after{content:"\f8dc\f8dc"}.fa-duotone.fa-square-2:after,.fad.fa-square-2:after{content:"\e257\e257"}.fa-duotone.fa-field-hockey-stick-ball:after,.fa-duotone.fa-field-hockey:after,.fad.fa-field-hockey-stick-ball:after,.fad.fa-field-hockey:after{content:"\f44c\f44c"}.fa-duotone.fa-arrow-up-square-triangle:after,.fa-duotone.fa-sort-shapes-up-alt:after,.fad.fa-arrow-up-square-triangle:after,.fad.fa-sort-shapes-up-alt:after{content:"\f88b\f88b"}.fa-duotone.fa-face-scream:after,.fad.fa-face-scream:after{content:"\e38b\e38b"}.fa-duotone.fa-square-m:after,.fad.fa-square-m:after{content:"\e276\e276"}.fa-duotone.fa-camera-web:after,.fa-duotone.fa-webcam:after,.fad.fa-camera-web:after,.fad.fa-webcam:after{content:"\f832\f832"}.fa-duotone.fa-comment-arrow-down:after,.fad.fa-comment-arrow-down:after{content:"\e143\e143"}.fa-duotone.fa-lightbulb-cfl:after,.fad.fa-lightbulb-cfl:after{content:"\e5a6\e5a6"}.fa-duotone.fa-window-frame-open:after,.fad.fa-window-frame-open:after{content:"\e050\e050"}.fa-duotone.fa-face-kiss:after,.fa-duotone.fa-kiss:after,.fad.fa-face-kiss:after,.fad.fa-kiss:after{content:"\f596\f596"}.fa-duotone.fa-bridge-circle-xmark:after,.fad.fa-bridge-circle-xmark:after{content:"\e4cb\e4cb"}.fa-duotone.fa-period:after,.fad.fa-period:after{content:"\2e\2e"}.fa-duotone.fa-face-grin-tongue:after,.fa-duotone.fa-grin-tongue:after,.fad.fa-face-grin-tongue:after,.fad.fa-grin-tongue:after{content:"\f589\f589"}.fa-duotone.fa-up-to-dotted-line:after,.fad.fa-up-to-dotted-line:after{content:"\e457\e457"}.fa-duotone.fa-thought-bubble:after,.fad.fa-thought-bubble:after{content:"\e32e\e32e"}.fa-duotone.fa-skeleton-ribs:after,.fad.fa-skeleton-ribs:after{content:"\e5cb\e5cb"}.fa-duotone.fa-raygun:after,.fad.fa-raygun:after{content:"\e025\e025"}.fa-duotone.fa-flute:after,.fad.fa-flute:after{content:"\f8b9\f8b9"}.fa-duotone.fa-acorn:after,.fad.fa-acorn:after{content:"\f6ae\f6ae"}.fa-duotone.fa-video-arrow-up-right:after,.fad.fa-video-arrow-up-right:after{content:"\e2c9\e2c9"}.fa-duotone.fa-grate-droplet:after,.fad.fa-grate-droplet:after{content:"\e194\e194"}.fa-duotone.fa-seal-exclamation:after,.fad.fa-seal-exclamation:after{content:"\e242\e242"}.fa-duotone.fa-chess-bishop:after,.fad.fa-chess-bishop:after{content:"\f43a\f43a"}.fa-duotone.fa-message-sms:after,.fad.fa-message-sms:after{content:"\e1e5\e1e5"}.fa-duotone.fa-coffee-beans:after,.fad.fa-coffee-beans:after{content:"\e13f\e13f"}.fa-duotone.fa-hat-witch:after,.fad.fa-hat-witch:after{content:"\f6e7\f6e7"}.fa-duotone.fa-face-grin-wink:after,.fa-duotone.fa-grin-wink:after,.fad.fa-face-grin-wink:after,.fad.fa-grin-wink:after{content:"\f58c\f58c"}.fa-duotone.fa-clock-three-thirty:after,.fad.fa-clock-three-thirty:after{content:"\e357\e357"}.fa-duotone.fa-deaf:after,.fa-duotone.fa-deafness:after,.fa-duotone.fa-ear-deaf:after,.fa-duotone.fa-hard-of-hearing:after,.fad.fa-deaf:after,.fad.fa-deafness:after,.fad.fa-ear-deaf:after,.fad.fa-hard-of-hearing:after{content:"\f2a4\f2a4"}.fa-duotone.fa-alarm-clock:after,.fad.fa-alarm-clock:after{content:"\f34e\f34e"}.fa-duotone.fa-eclipse:after,.fad.fa-eclipse:after{content:"\f749\f749"}.fa-duotone.fa-face-relieved:after,.fad.fa-face-relieved:after{content:"\e389\e389"}.fa-duotone.fa-road-circle-check:after,.fad.fa-road-circle-check:after{content:"\e564\e564"}.fa-duotone.fa-dice-five:after,.fad.fa-dice-five:after{content:"\f523\f523"}.fa-duotone.fa-minus-octagon:after,.fa-duotone.fa-octagon-minus:after,.fad.fa-minus-octagon:after,.fad.fa-octagon-minus:after{content:"\f308\f308"}.fa-duotone.fa-rss-square:after,.fa-duotone.fa-square-rss:after,.fad.fa-rss-square:after,.fad.fa-square-rss:after{content:"\f143\f143"}.fa-duotone.fa-face-zany:after,.fad.fa-face-zany:after{content:"\e3a4\e3a4"}.fa-duotone.fa-tricycle:after,.fad.fa-tricycle:after{content:"\e5c3\e5c3"}.fa-duotone.fa-land-mine-on:after,.fad.fa-land-mine-on:after{content:"\e51b\e51b"}.fa-duotone.fa-square-arrow-up-left:after,.fad.fa-square-arrow-up-left:after{content:"\e263\e263"}.fa-duotone.fa-i-cursor:after,.fad.fa-i-cursor:after{content:"\f246\f246"}.fa-duotone.fa-chart-mixed-up-circle-dollar:after,.fad.fa-chart-mixed-up-circle-dollar:after{content:"\e5d9\e5d9"}.fa-duotone.fa-salt-shaker:after,.fad.fa-salt-shaker:after{content:"\e446\e446"}.fa-duotone.fa-stamp:after,.fad.fa-stamp:after{content:"\f5bf\f5bf"}.fa-duotone.fa-file-plus:after,.fad.fa-file-plus:after{content:"\f319\f319"}.fa-duotone.fa-draw-square:after,.fad.fa-draw-square:after{content:"\f5ef\f5ef"}.fa-duotone.fa-toilet-paper-reverse-slash:after,.fa-duotone.fa-toilet-paper-under-slash:after,.fad.fa-toilet-paper-reverse-slash:after,.fad.fa-toilet-paper-under-slash:after{content:"\e2a1\e2a1"}.fa-duotone.fa-stairs:after,.fad.fa-stairs:after{content:"\e289\e289"}.fa-duotone.fa-drone-alt:after,.fa-duotone.fa-drone-front:after,.fad.fa-drone-alt:after,.fad.fa-drone-front:after{content:"\f860\f860"}.fa-duotone.fa-glass-empty:after,.fad.fa-glass-empty:after{content:"\e191\e191"}.fa-duotone.fa-dial-high:after,.fad.fa-dial-high:after{content:"\e15c\e15c"}.fa-duotone.fa-user-construction:after,.fa-duotone.fa-user-hard-hat:after,.fa-duotone.fa-user-helmet-safety:after,.fad.fa-user-construction:after,.fad.fa-user-hard-hat:after,.fad.fa-user-helmet-safety:after{content:"\f82c\f82c"}.fa-duotone.fa-i:after,.fad.fa-i:after{content:"\49\49"}.fa-duotone.fa-hryvnia-sign:after,.fa-duotone.fa-hryvnia:after,.fad.fa-hryvnia-sign:after,.fad.fa-hryvnia:after{content:"\f6f2\f6f2"}.fa-duotone.fa-arrow-down-left-and-arrow-up-right-to-center:after,.fad.fa-arrow-down-left-and-arrow-up-right-to-center:after{content:"\e092\e092"}.fa-duotone.fa-pills:after,.fad.fa-pills:after{content:"\f484\f484"}.fa-duotone.fa-face-grin-wide:after,.fa-duotone.fa-grin-alt:after,.fad.fa-face-grin-wide:after,.fad.fa-grin-alt:after{content:"\f581\f581"}.fa-duotone.fa-tooth:after,.fad.fa-tooth:after{content:"\f5c9\f5c9"}.fa-duotone.fa-basketball-hoop:after,.fad.fa-basketball-hoop:after{content:"\f435\f435"}.fa-duotone.fa-objects-align-bottom:after,.fad.fa-objects-align-bottom:after{content:"\e3bb\e3bb"}.fa-duotone.fa-v:after,.fad.fa-v:after{content:"\56\56"}.fa-duotone.fa-sparkles:after,.fad.fa-sparkles:after{content:"\f890\f890"}.fa-duotone.fa-squid:after,.fad.fa-squid:after{content:"\e450\e450"}.fa-duotone.fa-leafy-green:after,.fad.fa-leafy-green:after{content:"\e41d\e41d"}.fa-duotone.fa-circle-arrow-up-right:after,.fad.fa-circle-arrow-up-right:after{content:"\e0fc\e0fc"}.fa-duotone.fa-calendars:after,.fad.fa-calendars:after{content:"\e0d7\e0d7"}.fa-duotone.fa-bangladeshi-taka-sign:after,.fad.fa-bangladeshi-taka-sign:after{content:"\e2e6\e2e6"}.fa-duotone.fa-bicycle:after,.fad.fa-bicycle:after{content:"\f206\f206"}.fa-duotone.fa-hammer-war:after,.fad.fa-hammer-war:after{content:"\f6e4\f6e4"}.fa-duotone.fa-circle-d:after,.fad.fa-circle-d:after{content:"\e104\e104"}.fa-duotone.fa-spider-black-widow:after,.fad.fa-spider-black-widow:after{content:"\f718\f718"}.fa-duotone.fa-rod-asclepius:after,.fa-duotone.fa-rod-snake:after,.fa-duotone.fa-staff-aesculapius:after,.fa-duotone.fa-staff-snake:after,.fad.fa-rod-asclepius:after,.fad.fa-rod-snake:after,.fad.fa-staff-aesculapius:after,.fad.fa-staff-snake:after{content:"\e579\e579"}.fa-duotone.fa-pear:after,.fad.fa-pear:after{content:"\e20c\e20c"}.fa-duotone.fa-head-side-cough-slash:after,.fad.fa-head-side-cough-slash:after{content:"\e062\e062"}.fa-duotone.fa-triangle:after,.fad.fa-triangle:after{content:"\f2ec\f2ec"}.fa-duotone.fa-apartment:after,.fad.fa-apartment:after{content:"\e468\e468"}.fa-duotone.fa-ambulance:after,.fa-duotone.fa-truck-medical:after,.fad.fa-ambulance:after,.fad.fa-truck-medical:after{content:"\f0f9\f0f9"}.fa-duotone.fa-pepper:after,.fad.fa-pepper:after{content:"\e432\e432"}.fa-duotone.fa-piano:after,.fad.fa-piano:after{content:"\f8d4\f8d4"}.fa-duotone.fa-gun-squirt:after,.fad.fa-gun-squirt:after{content:"\e19d\e19d"}.fa-duotone.fa-wheat-awn-circle-exclamation:after,.fad.fa-wheat-awn-circle-exclamation:after{content:"\e598\e598"}.fa-duotone.fa-snowman:after,.fad.fa-snowman:after{content:"\f7d0\f7d0"}.fa-duotone.fa-user-alien:after,.fad.fa-user-alien:after{content:"\e04a\e04a"}.fa-duotone.fa-shield-check:after,.fad.fa-shield-check:after{content:"\f2f7\f2f7"}.fa-duotone.fa-mortar-pestle:after,.fad.fa-mortar-pestle:after{content:"\f5a7\f5a7"}.fa-duotone.fa-road-barrier:after,.fad.fa-road-barrier:after{content:"\e562\e562"}.fa-duotone.fa-chart-candlestick:after,.fad.fa-chart-candlestick:after{content:"\e0e2\e0e2"}.fa-duotone.fa-briefcase-blank:after,.fad.fa-briefcase-blank:after{content:"\e0c8\e0c8"}.fa-duotone.fa-school:after,.fad.fa-school:after{content:"\f549\f549"}.fa-duotone.fa-igloo:after,.fad.fa-igloo:after{content:"\f7ae\f7ae"}.fa-duotone.fa-bracket-round:after,.fa-duotone.fa-parenthesis:after,.fad.fa-bracket-round:after,.fad.fa-parenthesis:after{content:"\28\28"}.fa-duotone.fa-joint:after,.fad.fa-joint:after{content:"\f595\f595"}.fa-duotone.fa-horse-saddle:after,.fad.fa-horse-saddle:after{content:"\f8c3\f8c3"}.fa-duotone.fa-mug-marshmallows:after,.fad.fa-mug-marshmallows:after{content:"\f7b7\f7b7"}.fa-duotone.fa-filters:after,.fad.fa-filters:after{content:"\e17e\e17e"}.fa-duotone.fa-bell-on:after,.fad.fa-bell-on:after{content:"\f8fa\f8fa"}.fa-duotone.fa-angle-right:after,.fad.fa-angle-right:after{content:"\f105\f105"}.fa-duotone.fa-dial-med:after,.fad.fa-dial-med:after{content:"\e15f\e15f"}.fa-duotone.fa-horse:after,.fad.fa-horse:after{content:"\f6f0\f6f0"}.fa-duotone.fa-q:after,.fad.fa-q:after{content:"\51\51"}.fa-duotone.fa-monitor-heart-rate:after,.fa-duotone.fa-monitor-waveform:after,.fad.fa-monitor-heart-rate:after,.fad.fa-monitor-waveform:after{content:"\f611\f611"}.fa-duotone.fa-link-simple:after,.fad.fa-link-simple:after{content:"\e1cd\e1cd"}.fa-duotone.fa-whistle:after,.fad.fa-whistle:after{content:"\f460\f460"}.fa-duotone.fa-g:after,.fad.fa-g:after{content:"\47\47"}.fa-duotone.fa-fragile:after,.fa-duotone.fa-wine-glass-crack:after,.fad.fa-fragile:after,.fad.fa-wine-glass-crack:after{content:"\f4bb\f4bb"}.fa-duotone.fa-slot-machine:after,.fad.fa-slot-machine:after{content:"\e3ce\e3ce"}.fa-duotone.fa-notes-medical:after,.fad.fa-notes-medical:after{content:"\f481\f481"}.fa-duotone.fa-car-wash:after,.fad.fa-car-wash:after{content:"\f5e6\f5e6"}.fa-duotone.fa-escalator:after,.fad.fa-escalator:after{content:"\e171\e171"}.fa-duotone.fa-comment-image:after,.fad.fa-comment-image:after{content:"\e148\e148"}.fa-duotone.fa-temperature-2:after,.fa-duotone.fa-temperature-half:after,.fa-duotone.fa-thermometer-2:after,.fa-duotone.fa-thermometer-half:after,.fad.fa-temperature-2:after,.fad.fa-temperature-half:after,.fad.fa-thermometer-2:after,.fad.fa-thermometer-half:after{content:"\f2c9\f2c9"}.fa-duotone.fa-dong-sign:after,.fad.fa-dong-sign:after{content:"\e169\e169"}.fa-duotone.fa-donut:after,.fa-duotone.fa-doughnut:after,.fad.fa-donut:after,.fad.fa-doughnut:after{content:"\e406\e406"}.fa-duotone.fa-capsules:after,.fad.fa-capsules:after{content:"\f46b\f46b"}.fa-duotone.fa-poo-bolt:after,.fa-duotone.fa-poo-storm:after,.fad.fa-poo-bolt:after,.fad.fa-poo-storm:after{content:"\f75a\f75a"}.fa-duotone.fa-tally-1:after,.fad.fa-tally-1:after{content:"\e294\e294"}.fa-duotone.fa-face-frown-open:after,.fa-duotone.fa-frown-open:after,.fad.fa-face-frown-open:after,.fad.fa-frown-open:after{content:"\f57a\f57a"}.fa-duotone.fa-square-dashed:after,.fad.fa-square-dashed:after{content:"\e269\e269"}.fa-duotone.fa-square-j:after,.fad.fa-square-j:after{content:"\e273\e273"}.fa-duotone.fa-hand-point-up:after,.fad.fa-hand-point-up:after{content:"\f0a6\f0a6"}.fa-duotone.fa-money-bill:after,.fad.fa-money-bill:after{content:"\f0d6\f0d6"}.fa-duotone.fa-arrow-up-big-small:after,.fa-duotone.fa-sort-size-up:after,.fad.fa-arrow-up-big-small:after,.fad.fa-sort-size-up:after{content:"\f88e\f88e"}.fa-duotone.fa-barcode-read:after,.fad.fa-barcode-read:after{content:"\f464\f464"}.fa-duotone.fa-baguette:after,.fad.fa-baguette:after{content:"\e3d8\e3d8"}.fa-duotone.fa-bowl-soft-serve:after,.fad.fa-bowl-soft-serve:after{content:"\e46b\e46b"}.fa-duotone.fa-face-holding-back-tears:after,.fad.fa-face-holding-back-tears:after{content:"\e482\e482"}.fa-duotone.fa-arrow-alt-square-up:after,.fa-duotone.fa-square-up:after,.fad.fa-arrow-alt-square-up:after,.fad.fa-square-up:after{content:"\f353\f353"}.fa-duotone.fa-subway-tunnel:after,.fa-duotone.fa-train-subway-tunnel:after,.fad.fa-subway-tunnel:after,.fad.fa-train-subway-tunnel:after{content:"\e2a3\e2a3"}.fa-duotone.fa-exclamation-square:after,.fa-duotone.fa-square-exclamation:after,.fad.fa-exclamation-square:after,.fad.fa-square-exclamation:after{content:"\f321\f321"}.fa-duotone.fa-semicolon:after,.fad.fa-semicolon:after{content:"\3b\3b"}.fa-duotone.fa-bookmark:after,.fad.fa-bookmark:after{content:"\f02e\f02e"}.fa-duotone.fa-fan-table:after,.fad.fa-fan-table:after{content:"\e004\e004"}.fa-duotone.fa-align-justify:after,.fad.fa-align-justify:after{content:"\f039\f039"}.fa-duotone.fa-battery-1:after,.fa-duotone.fa-battery-low:after,.fad.fa-battery-1:after,.fad.fa-battery-low:after{content:"\e0b1\e0b1"}.fa-duotone.fa-credit-card-front:after,.fad.fa-credit-card-front:after{content:"\f38a\f38a"}.fa-duotone.fa-brain-arrow-curved-right:after,.fa-duotone.fa-mind-share:after,.fad.fa-brain-arrow-curved-right:after,.fad.fa-mind-share:after{content:"\f677\f677"}.fa-duotone.fa-umbrella-beach:after,.fad.fa-umbrella-beach:after{content:"\f5ca\f5ca"}.fa-duotone.fa-helmet-un:after,.fad.fa-helmet-un:after{content:"\e503\e503"}.fa-duotone.fa-location-smile:after,.fa-duotone.fa-map-marker-smile:after,.fad.fa-location-smile:after,.fad.fa-map-marker-smile:after{content:"\f60d\f60d"}.fa-duotone.fa-arrow-left-to-line:after,.fa-duotone.fa-arrow-to-left:after,.fad.fa-arrow-left-to-line:after,.fad.fa-arrow-to-left:after{content:"\f33e\f33e"}.fa-duotone.fa-bullseye:after,.fad.fa-bullseye:after{content:"\f140\f140"}.fa-duotone.fa-nigiri:after,.fa-duotone.fa-sushi:after,.fad.fa-nigiri:after,.fad.fa-sushi:after{content:"\e48a\e48a"}.fa-duotone.fa-comment-alt-captions:after,.fa-duotone.fa-message-captions:after,.fad.fa-comment-alt-captions:after,.fad.fa-message-captions:after{content:"\e1de\e1de"}.fa-duotone.fa-trash-list:after,.fad.fa-trash-list:after{content:"\e2b1\e2b1"}.fa-duotone.fa-bacon:after,.fad.fa-bacon:after{content:"\f7e5\f7e5"}.fa-duotone.fa-option:after,.fad.fa-option:after{content:"\e318\e318"}.fa-duotone.fa-raccoon:after,.fad.fa-raccoon:after{content:"\e613\e613"}.fa-duotone.fa-hand-point-down:after,.fad.fa-hand-point-down:after{content:"\f0a7\f0a7"}.fa-duotone.fa-arrow-up-from-bracket:after,.fad.fa-arrow-up-from-bracket:after{content:"\e09a\e09a"}.fa-duotone.fa-head-side-gear:after,.fad.fa-head-side-gear:after{content:"\e611\e611"}.fa-duotone.fa-trash-plus:after,.fad.fa-trash-plus:after{content:"\e2b2\e2b2"}.fa-duotone.fa-objects-align-top:after,.fad.fa-objects-align-top:after{content:"\e3c0\e3c0"}.fa-duotone.fa-folder-blank:after,.fa-duotone.fa-folder:after,.fad.fa-folder-blank:after,.fad.fa-folder:after{content:"\f07b\f07b"}.fa-duotone.fa-face-anxious-sweat:after,.fad.fa-face-anxious-sweat:after{content:"\e36a\e36a"}.fa-duotone.fa-credit-card-blank:after,.fad.fa-credit-card-blank:after{content:"\f389\f389"}.fa-duotone.fa-file-medical-alt:after,.fa-duotone.fa-file-waveform:after,.fad.fa-file-medical-alt:after,.fad.fa-file-waveform:after{content:"\f478\f478"}.fa-duotone.fa-microchip-ai:after,.fad.fa-microchip-ai:after{content:"\e1ec\e1ec"}.fa-duotone.fa-mug:after,.fad.fa-mug:after{content:"\f874\f874"}.fa-duotone.fa-plane-up-slash:after,.fad.fa-plane-up-slash:after{content:"\e22e\e22e"}.fa-duotone.fa-radiation:after,.fad.fa-radiation:after{content:"\f7b9\f7b9"}.fa-duotone.fa-pen-circle:after,.fad.fa-pen-circle:after{content:"\e20e\e20e"}.fa-duotone.fa-bag-seedling:after,.fad.fa-bag-seedling:after{content:"\e5f2\e5f2"}.fa-duotone.fa-chart-simple:after,.fad.fa-chart-simple:after{content:"\e473\e473"}.fa-duotone.fa-crutches:after,.fad.fa-crutches:after{content:"\f7f8\f7f8"}.fa-duotone.fa-circle-parking:after,.fa-duotone.fa-parking-circle:after,.fad.fa-circle-parking:after,.fad.fa-parking-circle:after{content:"\f615\f615"}.fa-duotone.fa-mars-stroke:after,.fad.fa-mars-stroke:after{content:"\f229\f229"}.fa-duotone.fa-leaf-oak:after,.fad.fa-leaf-oak:after{content:"\f6f7\f6f7"}.fa-duotone.fa-square-bolt:after,.fad.fa-square-bolt:after{content:"\e265\e265"}.fa-duotone.fa-vial:after,.fad.fa-vial:after{content:"\f492\f492"}.fa-duotone.fa-dashboard:after,.fa-duotone.fa-gauge-med:after,.fa-duotone.fa-gauge:after,.fa-duotone.fa-tachometer-alt-average:after,.fad.fa-dashboard:after,.fad.fa-gauge-med:after,.fad.fa-gauge:after,.fad.fa-tachometer-alt-average:after{content:"\f624\f624"}.fa-duotone.fa-magic-wand-sparkles:after,.fa-duotone.fa-wand-magic-sparkles:after,.fad.fa-magic-wand-sparkles:after,.fad.fa-wand-magic-sparkles:after{content:"\e2ca\e2ca"}.fa-duotone.fa-lambda:after,.fad.fa-lambda:after{content:"\f66e\f66e"}.fa-duotone.fa-e:after,.fad.fa-e:after{content:"\45\45"}.fa-duotone.fa-pizza:after,.fad.fa-pizza:after{content:"\f817\f817"}.fa-duotone.fa-bowl-chopsticks-noodles:after,.fad.fa-bowl-chopsticks-noodles:after{content:"\e2ea\e2ea"}.fa-duotone.fa-h3:after,.fad.fa-h3:after{content:"\f315\f315"}.fa-duotone.fa-pen-alt:after,.fa-duotone.fa-pen-clip:after,.fad.fa-pen-alt:after,.fad.fa-pen-clip:after{content:"\f305\f305"}.fa-duotone.fa-bridge-circle-exclamation:after,.fad.fa-bridge-circle-exclamation:after{content:"\e4ca\e4ca"}.fa-duotone.fa-badge-percent:after,.fad.fa-badge-percent:after{content:"\f646\f646"}.fa-duotone.fa-user:after,.fad.fa-user:after{content:"\f007\f007"}.fa-duotone.fa-sensor:after,.fad.fa-sensor:after{content:"\e028\e028"}.fa-duotone.fa-comma:after,.fad.fa-comma:after{content:"\2c\2c"}.fa-duotone.fa-school-circle-check:after,.fad.fa-school-circle-check:after{content:"\e56b\e56b"}.fa-duotone.fa-toilet-paper-reverse:after,.fa-duotone.fa-toilet-paper-under:after,.fad.fa-toilet-paper-reverse:after,.fad.fa-toilet-paper-under:after{content:"\e2a0\e2a0"}.fa-duotone.fa-light-emergency:after,.fad.fa-light-emergency:after{content:"\e41f\e41f"}.fa-duotone.fa-arrow-down-to-arc:after,.fad.fa-arrow-down-to-arc:after{content:"\e4ae\e4ae"}.fa-duotone.fa-dumpster:after,.fad.fa-dumpster:after{content:"\f793\f793"}.fa-duotone.fa-shuttle-van:after,.fa-duotone.fa-van-shuttle:after,.fad.fa-shuttle-van:after,.fad.fa-van-shuttle:after{content:"\f5b6\f5b6"}.fa-duotone.fa-building-user:after,.fad.fa-building-user:after{content:"\e4da\e4da"}.fa-duotone.fa-light-switch:after,.fad.fa-light-switch:after{content:"\e017\e017"}.fa-duotone.fa-caret-square-left:after,.fa-duotone.fa-square-caret-left:after,.fad.fa-caret-square-left:after,.fad.fa-square-caret-left:after{content:"\f191\f191"}.fa-duotone.fa-highlighter:after,.fad.fa-highlighter:after{content:"\f591\f591"}.fa-duotone.fa-heart-rate:after,.fa-duotone.fa-wave-pulse:after,.fad.fa-heart-rate:after,.fad.fa-wave-pulse:after{content:"\f5f8\f5f8"}.fa-duotone.fa-key:after,.fad.fa-key:after{content:"\f084\f084"}.fa-duotone.fa-hat-santa:after,.fad.fa-hat-santa:after{content:"\f7a7\f7a7"}.fa-duotone.fa-tamale:after,.fad.fa-tamale:after{content:"\e451\e451"}.fa-duotone.fa-box-check:after,.fad.fa-box-check:after{content:"\f467\f467"}.fa-duotone.fa-bullhorn:after,.fad.fa-bullhorn:after{content:"\f0a1\f0a1"}.fa-duotone.fa-steak:after,.fad.fa-steak:after{content:"\f824\f824"}.fa-duotone.fa-location-crosshairs-slash:after,.fa-duotone.fa-location-slash:after,.fad.fa-location-crosshairs-slash:after,.fad.fa-location-slash:after{content:"\f603\f603"}.fa-duotone.fa-person-dolly:after,.fad.fa-person-dolly:after{content:"\f4d0\f4d0"}.fa-duotone.fa-globe:after,.fad.fa-globe:after{content:"\f0ac\f0ac"}.fa-duotone.fa-synagogue:after,.fad.fa-synagogue:after{content:"\f69b\f69b"}.fa-duotone.fa-file-chart-column:after,.fa-duotone.fa-file-chart-line:after,.fad.fa-file-chart-column:after,.fad.fa-file-chart-line:after{content:"\f659\f659"}.fa-duotone.fa-person-half-dress:after,.fad.fa-person-half-dress:after{content:"\e548\e548"}.fa-duotone.fa-folder-image:after,.fad.fa-folder-image:after{content:"\e18a\e18a"}.fa-duotone.fa-calendar-edit:after,.fa-duotone.fa-calendar-pen:after,.fad.fa-calendar-edit:after,.fad.fa-calendar-pen:after{content:"\f333\f333"}.fa-duotone.fa-road-bridge:after,.fad.fa-road-bridge:after{content:"\e563\e563"}.fa-duotone.fa-face-smile-tear:after,.fad.fa-face-smile-tear:after{content:"\e393\e393"}.fa-duotone.fa-comment-alt-plus:after,.fa-duotone.fa-message-plus:after,.fad.fa-comment-alt-plus:after,.fad.fa-message-plus:after{content:"\f4a8\f4a8"}.fa-duotone.fa-location-arrow:after,.fad.fa-location-arrow:after{content:"\f124\f124"}.fa-duotone.fa-c:after,.fad.fa-c:after{content:"\43\43"}.fa-duotone.fa-tablet-button:after,.fad.fa-tablet-button:after{content:"\f10a\f10a"}.fa-duotone.fa-person-dress-fairy:after,.fad.fa-person-dress-fairy:after{content:"\e607\e607"}.fa-duotone.fa-rectangle-history-circle-user:after,.fad.fa-rectangle-history-circle-user:after{content:"\e4a4\e4a4"}.fa-duotone.fa-building-lock:after,.fad.fa-building-lock:after{content:"\e4d6\e4d6"}.fa-duotone.fa-chart-line-up:after,.fad.fa-chart-line-up:after{content:"\e0e5\e0e5"}.fa-duotone.fa-mailbox:after,.fad.fa-mailbox:after{content:"\f813\f813"}.fa-duotone.fa-truck-bolt:after,.fad.fa-truck-bolt:after{content:"\e3d0\e3d0"}.fa-duotone.fa-pizza-slice:after,.fad.fa-pizza-slice:after{content:"\f818\f818"}.fa-duotone.fa-money-bill-wave:after,.fad.fa-money-bill-wave:after{content:"\f53a\f53a"}.fa-duotone.fa-area-chart:after,.fa-duotone.fa-chart-area:after,.fad.fa-area-chart:after,.fad.fa-chart-area:after{content:"\f1fe\f1fe"}.fa-duotone.fa-house-flag:after,.fad.fa-house-flag:after{content:"\e50d\e50d"}.fa-duotone.fa-circle-three-quarters-stroke:after,.fad.fa-circle-three-quarters-stroke:after{content:"\e5d4\e5d4"}.fa-duotone.fa-person-circle-minus:after,.fad.fa-person-circle-minus:after{content:"\e540\e540"}.fa-duotone.fa-scalpel:after,.fad.fa-scalpel:after{content:"\f61d\f61d"}.fa-duotone.fa-ban:after,.fa-duotone.fa-cancel:after,.fad.fa-ban:after,.fad.fa-cancel:after{content:"\f05e\f05e"}.fa-duotone.fa-bell-exclamation:after,.fad.fa-bell-exclamation:after{content:"\f848\f848"}.fa-duotone.fa-bookmark-circle:after,.fa-duotone.fa-circle-bookmark:after,.fad.fa-bookmark-circle:after,.fad.fa-circle-bookmark:after{content:"\e100\e100"}.fa-duotone.fa-egg-fried:after,.fad.fa-egg-fried:after{content:"\f7fc\f7fc"}.fa-duotone.fa-face-weary:after,.fad.fa-face-weary:after{content:"\e3a1\e3a1"}.fa-duotone.fa-uniform-martial-arts:after,.fad.fa-uniform-martial-arts:after{content:"\e3d1\e3d1"}.fa-duotone.fa-camera-rotate:after,.fad.fa-camera-rotate:after{content:"\e0d8\e0d8"}.fa-duotone.fa-sun-dust:after,.fad.fa-sun-dust:after{content:"\f764\f764"}.fa-duotone.fa-comment-text:after,.fad.fa-comment-text:after{content:"\e14d\e14d"}.fa-duotone.fa-air-freshener:after,.fa-duotone.fa-spray-can-sparkles:after,.fad.fa-air-freshener:after,.fad.fa-spray-can-sparkles:after{content:"\f5d0\f5d0"}.fa-duotone.fa-signal-alt-4:after,.fa-duotone.fa-signal-alt:after,.fa-duotone.fa-signal-bars-strong:after,.fa-duotone.fa-signal-bars:after,.fad.fa-signal-alt-4:after,.fad.fa-signal-alt:after,.fad.fa-signal-bars-strong:after,.fad.fa-signal-bars:after{content:"\f690\f690"}.fa-duotone.fa-diamond-exclamation:after,.fad.fa-diamond-exclamation:after{content:"\e405\e405"}.fa-duotone.fa-star:after,.fad.fa-star:after{content:"\f005\f005"}.fa-duotone.fa-dial-min:after,.fad.fa-dial-min:after{content:"\e161\e161"}.fa-duotone.fa-repeat:after,.fad.fa-repeat:after{content:"\f363\f363"}.fa-duotone.fa-cross:after,.fad.fa-cross:after{content:"\f654\f654"}.fa-duotone.fa-file-caret-down:after,.fa-duotone.fa-page-caret-down:after,.fad.fa-file-caret-down:after,.fad.fa-page-caret-down:after{content:"\e429\e429"}.fa-duotone.fa-box:after,.fad.fa-box:after{content:"\f466\f466"}.fa-duotone.fa-venus-mars:after,.fad.fa-venus-mars:after{content:"\f228\f228"}.fa-duotone.fa-clock-seven-thirty:after,.fad.fa-clock-seven-thirty:after{content:"\e351\e351"}.fa-duotone.fa-arrow-pointer:after,.fa-duotone.fa-mouse-pointer:after,.fad.fa-arrow-pointer:after,.fad.fa-mouse-pointer:after{content:"\f245\f245"}.fa-duotone.fa-clock-four-thirty:after,.fad.fa-clock-four-thirty:after{content:"\e34b\e34b"}.fa-duotone.fa-signal-alt-3:after,.fa-duotone.fa-signal-bars-good:after,.fad.fa-signal-alt-3:after,.fad.fa-signal-bars-good:after{content:"\f693\f693"}.fa-duotone.fa-cactus:after,.fad.fa-cactus:after{content:"\f8a7\f8a7"}.fa-duotone.fa-lightbulb-gear:after,.fad.fa-lightbulb-gear:after{content:"\e5fd\e5fd"}.fa-duotone.fa-expand-arrows-alt:after,.fa-duotone.fa-maximize:after,.fad.fa-expand-arrows-alt:after,.fad.fa-maximize:after{content:"\f31e\f31e"}.fa-duotone.fa-charging-station:after,.fad.fa-charging-station:after{content:"\f5e7\f5e7"}.fa-duotone.fa-shapes:after,.fa-duotone.fa-triangle-circle-square:after,.fad.fa-shapes:after,.fad.fa-triangle-circle-square:after{content:"\f61f\f61f"}.fa-duotone.fa-plane-tail:after,.fad.fa-plane-tail:after{content:"\e22c\e22c"}.fa-duotone.fa-gauge-simple-max:after,.fa-duotone.fa-tachometer-fastest:after,.fad.fa-gauge-simple-max:after,.fad.fa-tachometer-fastest:after{content:"\f62b\f62b"}.fa-duotone.fa-circle-u:after,.fad.fa-circle-u:after{content:"\e127\e127"}.fa-duotone.fa-shield-slash:after,.fad.fa-shield-slash:after{content:"\e24b\e24b"}.fa-duotone.fa-phone-square-down:after,.fa-duotone.fa-square-phone-hangup:after,.fad.fa-phone-square-down:after,.fad.fa-square-phone-hangup:after{content:"\e27a\e27a"}.fa-duotone.fa-arrow-up-left:after,.fad.fa-arrow-up-left:after{content:"\e09d\e09d"}.fa-duotone.fa-transporter-1:after,.fad.fa-transporter-1:after{content:"\e043\e043"}.fa-duotone.fa-peanuts:after,.fad.fa-peanuts:after{content:"\e431\e431"}.fa-duotone.fa-random:after,.fa-duotone.fa-shuffle:after,.fad.fa-random:after,.fad.fa-shuffle:after{content:"\f074\f074"}.fa-duotone.fa-person-running:after,.fa-duotone.fa-running:after,.fad.fa-person-running:after,.fad.fa-running:after{content:"\f70c\f70c"}.fa-duotone.fa-mobile-retro:after,.fad.fa-mobile-retro:after{content:"\e527\e527"}.fa-duotone.fa-grip-lines-vertical:after,.fad.fa-grip-lines-vertical:after{content:"\f7a5\f7a5"}.fa-duotone.fa-bin-bottles-recycle:after,.fad.fa-bin-bottles-recycle:after{content:"\e5f6\e5f6"}.fa-duotone.fa-arrow-up-from-square:after,.fad.fa-arrow-up-from-square:after{content:"\e09c\e09c"}.fa-duotone.fa-file-dashed-line:after,.fa-duotone.fa-page-break:after,.fad.fa-file-dashed-line:after,.fad.fa-page-break:after{content:"\f877\f877"}.fa-duotone.fa-bracket-curly-right:after,.fad.fa-bracket-curly-right:after{content:"\7d\7d"}.fa-duotone.fa-spider:after,.fad.fa-spider:after{content:"\f717\f717"}.fa-duotone.fa-clock-three:after,.fad.fa-clock-three:after{content:"\e356\e356"}.fa-duotone.fa-hands-bound:after,.fad.fa-hands-bound:after{content:"\e4f9\e4f9"}.fa-duotone.fa-scalpel-line-dashed:after,.fa-duotone.fa-scalpel-path:after,.fad.fa-scalpel-line-dashed:after,.fad.fa-scalpel-path:after{content:"\f61e\f61e"}.fa-duotone.fa-file-invoice-dollar:after,.fad.fa-file-invoice-dollar:after{content:"\f571\f571"}.fa-duotone.fa-pipe-smoking:after,.fad.fa-pipe-smoking:after{content:"\e3c4\e3c4"}.fa-duotone.fa-face-astonished:after,.fad.fa-face-astonished:after{content:"\e36b\e36b"}.fa-duotone.fa-window:after,.fad.fa-window:after{content:"\f40e\f40e"}.fa-duotone.fa-plane-circle-exclamation:after,.fad.fa-plane-circle-exclamation:after{content:"\e556\e556"}.fa-duotone.fa-ear:after,.fad.fa-ear:after{content:"\f5f0\f5f0"}.fa-duotone.fa-file-lock:after,.fad.fa-file-lock:after{content:"\e3a6\e3a6"}.fa-duotone.fa-diagram-venn:after,.fad.fa-diagram-venn:after{content:"\e15a\e15a"}.fa-duotone.fa-x-ray:after,.fad.fa-x-ray:after{content:"\f497\f497"}.fa-duotone.fa-goal-net:after,.fad.fa-goal-net:after{content:"\e3ab\e3ab"}.fa-duotone.fa-coffin-cross:after,.fad.fa-coffin-cross:after{content:"\e051\e051"}.fa-duotone.fa-spell-check:after,.fad.fa-spell-check:after{content:"\f891\f891"}.fa-duotone.fa-location-xmark:after,.fa-duotone.fa-map-marker-times:after,.fa-duotone.fa-map-marker-xmark:after,.fad.fa-location-xmark:after,.fad.fa-map-marker-times:after,.fad.fa-map-marker-xmark:after{content:"\f60e\f60e"}.fa-duotone.fa-circle-quarter-stroke:after,.fad.fa-circle-quarter-stroke:after{content:"\e5d3\e5d3"}.fa-duotone.fa-lasso:after,.fad.fa-lasso:after{content:"\f8c8\f8c8"}.fa-duotone.fa-slash:after,.fad.fa-slash:after{content:"\f715\f715"}.fa-duotone.fa-person-to-portal:after,.fa-duotone.fa-portal-enter:after,.fad.fa-person-to-portal:after,.fad.fa-portal-enter:after{content:"\e022\e022"}.fa-duotone.fa-calendar-star:after,.fad.fa-calendar-star:after{content:"\f736\f736"}.fa-duotone.fa-computer-mouse:after,.fa-duotone.fa-mouse:after,.fad.fa-computer-mouse:after,.fad.fa-mouse:after{content:"\f8cc\f8cc"}.fa-duotone.fa-arrow-right-to-bracket:after,.fa-duotone.fa-sign-in:after,.fad.fa-arrow-right-to-bracket:after,.fad.fa-sign-in:after{content:"\f090\f090"}.fa-duotone.fa-pegasus:after,.fad.fa-pegasus:after{content:"\f703\f703"}.fa-duotone.fa-files-medical:after,.fad.fa-files-medical:after{content:"\f7fd\f7fd"}.fa-duotone.fa-nfc-lock:after,.fad.fa-nfc-lock:after{content:"\e1f8\e1f8"}.fa-duotone.fa-person-ski-lift:after,.fa-duotone.fa-ski-lift:after,.fad.fa-person-ski-lift:after,.fad.fa-ski-lift:after{content:"\f7c8\f7c8"}.fa-duotone.fa-square-6:after,.fad.fa-square-6:after{content:"\e25b\e25b"}.fa-duotone.fa-shop-slash:after,.fa-duotone.fa-store-alt-slash:after,.fad.fa-shop-slash:after,.fad.fa-store-alt-slash:after{content:"\e070\e070"}.fa-duotone.fa-wind-turbine:after,.fad.fa-wind-turbine:after{content:"\f89b\f89b"}.fa-duotone.fa-sliders-simple:after,.fad.fa-sliders-simple:after{content:"\e253\e253"}.fa-duotone.fa-grid-round:after,.fad.fa-grid-round:after{content:"\e5da\e5da"}.fa-duotone.fa-badge-sheriff:after,.fad.fa-badge-sheriff:after{content:"\f8a2\f8a2"}.fa-duotone.fa-server:after,.fad.fa-server:after{content:"\f233\f233"}.fa-duotone.fa-virus-covid-slash:after,.fad.fa-virus-covid-slash:after{content:"\e4a9\e4a9"}.fa-duotone.fa-intersection:after,.fad.fa-intersection:after{content:"\f668\f668"}.fa-duotone.fa-shop-lock:after,.fad.fa-shop-lock:after{content:"\e4a5\e4a5"}.fa-duotone.fa-family:after,.fad.fa-family:after{content:"\e300\e300"}.fa-duotone.fa-hourglass-1:after,.fa-duotone.fa-hourglass-start:after,.fad.fa-hourglass-1:after,.fad.fa-hourglass-start:after{content:"\f251\f251"}.fa-duotone.fa-user-hair-buns:after,.fad.fa-user-hair-buns:after{content:"\e3d3\e3d3"}.fa-duotone.fa-blender-phone:after,.fad.fa-blender-phone:after{content:"\f6b6\f6b6"}.fa-duotone.fa-hourglass-clock:after,.fad.fa-hourglass-clock:after{content:"\e41b\e41b"}.fa-duotone.fa-person-seat-reclined:after,.fad.fa-person-seat-reclined:after{content:"\e21f\e21f"}.fa-duotone.fa-paper-plane-alt:after,.fa-duotone.fa-paper-plane-top:after,.fa-duotone.fa-send:after,.fad.fa-paper-plane-alt:after,.fad.fa-paper-plane-top:after,.fad.fa-send:after{content:"\e20a\e20a"}.fa-duotone.fa-comment-alt-arrow-up:after,.fa-duotone.fa-message-arrow-up:after,.fad.fa-comment-alt-arrow-up:after,.fad.fa-message-arrow-up:after{content:"\e1dc\e1dc"}.fa-duotone.fa-lightbulb-exclamation:after,.fad.fa-lightbulb-exclamation:after{content:"\f671\f671"}.fa-duotone.fa-layer-group-minus:after,.fa-duotone.fa-layer-minus:after,.fad.fa-layer-group-minus:after,.fad.fa-layer-minus:after{content:"\f5fe\f5fe"}.fa-duotone.fa-chart-pie-simple-circle-currency:after,.fad.fa-chart-pie-simple-circle-currency:after{content:"\e604\e604"}.fa-duotone.fa-circle-e:after,.fad.fa-circle-e:after{content:"\e109\e109"}.fa-duotone.fa-building-wheat:after,.fad.fa-building-wheat:after{content:"\e4db\e4db"}.fa-duotone.fa-gauge-max:after,.fa-duotone.fa-tachometer-alt-fastest:after,.fad.fa-gauge-max:after,.fad.fa-tachometer-alt-fastest:after{content:"\f626\f626"}.fa-duotone.fa-person-breastfeeding:after,.fad.fa-person-breastfeeding:after{content:"\e53a\e53a"}.fa-duotone.fa-apostrophe:after,.fad.fa-apostrophe:after{content:"\27\27"}.fa-duotone.fa-fire-hydrant:after,.fad.fa-fire-hydrant:after{content:"\e17f\e17f"}.fa-duotone.fa-right-to-bracket:after,.fa-duotone.fa-sign-in-alt:after,.fad.fa-right-to-bracket:after,.fad.fa-sign-in-alt:after{content:"\f2f6\f2f6"}.fa-duotone.fa-video-plus:after,.fad.fa-video-plus:after{content:"\f4e1\f4e1"}.fa-duotone.fa-arrow-alt-square-right:after,.fa-duotone.fa-square-right:after,.fad.fa-arrow-alt-square-right:after,.fad.fa-square-right:after{content:"\f352\f352"}.fa-duotone.fa-comment-smile:after,.fad.fa-comment-smile:after{content:"\f4b4\f4b4"}.fa-duotone.fa-venus:after,.fad.fa-venus:after{content:"\f221\f221"}.fa-duotone.fa-passport:after,.fad.fa-passport:after{content:"\f5ab\f5ab"}.fa-duotone.fa-inbox-arrow-down:after,.fa-duotone.fa-inbox-in:after,.fad.fa-inbox-arrow-down:after,.fad.fa-inbox-in:after{content:"\f310\f310"}.fa-duotone.fa-heart-pulse:after,.fa-duotone.fa-heartbeat:after,.fad.fa-heart-pulse:after,.fad.fa-heartbeat:after{content:"\f21e\f21e"}.fa-duotone.fa-circle-8:after,.fad.fa-circle-8:after{content:"\e0f5\e0f5"}.fa-duotone.fa-clouds-moon:after,.fad.fa-clouds-moon:after{content:"\f745\f745"}.fa-duotone.fa-clock-ten-thirty:after,.fad.fa-clock-ten-thirty:after{content:"\e355\e355"}.fa-duotone.fa-people-carry-box:after,.fa-duotone.fa-people-carry:after,.fad.fa-people-carry-box:after,.fad.fa-people-carry:after{content:"\f4ce\f4ce"}.fa-duotone.fa-folder-user:after,.fad.fa-folder-user:after{content:"\e18e\e18e"}.fa-duotone.fa-trash-can-xmark:after,.fad.fa-trash-can-xmark:after{content:"\e2ae\e2ae"}.fa-duotone.fa-temperature-high:after,.fad.fa-temperature-high:after{content:"\f769\f769"}.fa-duotone.fa-microchip:after,.fad.fa-microchip:after{content:"\f2db\f2db"}.fa-duotone.fa-left-long-to-line:after,.fad.fa-left-long-to-line:after{content:"\e41e\e41e"}.fa-duotone.fa-crown:after,.fad.fa-crown:after{content:"\f521\f521"}.fa-duotone.fa-weight-hanging:after,.fad.fa-weight-hanging:after{content:"\f5cd\f5cd"}.fa-duotone.fa-xmarks-lines:after,.fad.fa-xmarks-lines:after{content:"\e59a\e59a"}.fa-duotone.fa-file-prescription:after,.fad.fa-file-prescription:after{content:"\f572\f572"}.fa-duotone.fa-calendar-range:after,.fad.fa-calendar-range:after{content:"\e0d6\e0d6"}.fa-duotone.fa-flower-daffodil:after,.fad.fa-flower-daffodil:after{content:"\f800\f800"}.fa-duotone.fa-hand-back-point-up:after,.fad.fa-hand-back-point-up:after{content:"\e1a2\e1a2"}.fa-duotone.fa-weight-scale:after,.fa-duotone.fa-weight:after,.fad.fa-weight-scale:after,.fad.fa-weight:after{content:"\f496\f496"}.fa-duotone.fa-arrow-up-to-arc:after,.fad.fa-arrow-up-to-arc:after{content:"\e617\e617"}.fa-duotone.fa-star-exclamation:after,.fad.fa-star-exclamation:after{content:"\f2f3\f2f3"}.fa-duotone.fa-books:after,.fad.fa-books:after{content:"\f5db\f5db"}.fa-duotone.fa-user-friends:after,.fa-duotone.fa-user-group:after,.fad.fa-user-friends:after,.fad.fa-user-group:after{content:"\f500\f500"}.fa-duotone.fa-arrow-up-a-z:after,.fa-duotone.fa-sort-alpha-up:after,.fad.fa-arrow-up-a-z:after,.fad.fa-sort-alpha-up:after{content:"\f15e\f15e"}.fa-duotone.fa-layer-group-plus:after,.fa-duotone.fa-layer-plus:after,.fad.fa-layer-group-plus:after,.fad.fa-layer-plus:after{content:"\f5ff\f5ff"}.fa-duotone.fa-play-pause:after,.fad.fa-play-pause:after{content:"\e22f\e22f"}.fa-duotone.fa-block-question:after,.fad.fa-block-question:after{content:"\e3dd\e3dd"}.fa-duotone.fa-snooze:after,.fa-duotone.fa-zzz:after,.fad.fa-snooze:after,.fad.fa-zzz:after{content:"\f880\f880"}.fa-duotone.fa-scanner-image:after,.fad.fa-scanner-image:after{content:"\f8f3\f8f3"}.fa-duotone.fa-tv-retro:after,.fad.fa-tv-retro:after{content:"\f401\f401"}.fa-duotone.fa-square-t:after,.fad.fa-square-t:after{content:"\e280\e280"}.fa-duotone.fa-barn-silo:after,.fa-duotone.fa-farm:after,.fad.fa-barn-silo:after,.fad.fa-farm:after{content:"\f864\f864"}.fa-duotone.fa-chess-knight:after,.fad.fa-chess-knight:after{content:"\f441\f441"}.fa-duotone.fa-bars-sort:after,.fad.fa-bars-sort:after{content:"\e0ae\e0ae"}.fa-duotone.fa-palette-boxes:after,.fa-duotone.fa-pallet-alt:after,.fa-duotone.fa-pallet-boxes:after,.fad.fa-palette-boxes:after,.fad.fa-pallet-alt:after,.fad.fa-pallet-boxes:after{content:"\f483\f483"}.fa-duotone.fa-face-laugh-squint:after,.fa-duotone.fa-laugh-squint:after,.fad.fa-face-laugh-squint:after,.fad.fa-laugh-squint:after{content:"\f59b\f59b"}.fa-duotone.fa-code-simple:after,.fad.fa-code-simple:after{content:"\e13d\e13d"}.fa-duotone.fa-bolt-slash:after,.fad.fa-bolt-slash:after{content:"\e0b8\e0b8"}.fa-duotone.fa-panel-fire:after,.fad.fa-panel-fire:after{content:"\e42f\e42f"}.fa-duotone.fa-binary-circle-check:after,.fad.fa-binary-circle-check:after{content:"\e33c\e33c"}.fa-duotone.fa-comment-minus:after,.fad.fa-comment-minus:after{content:"\f4b1\f4b1"}.fa-duotone.fa-burrito:after,.fad.fa-burrito:after{content:"\f7ed\f7ed"}.fa-duotone.fa-violin:after,.fad.fa-violin:after{content:"\f8ed\f8ed"}.fa-duotone.fa-objects-column:after,.fad.fa-objects-column:after{content:"\e3c1\e3c1"}.fa-duotone.fa-chevron-square-down:after,.fa-duotone.fa-square-chevron-down:after,.fad.fa-chevron-square-down:after,.fad.fa-square-chevron-down:after{content:"\f329\f329"}.fa-duotone.fa-comment-plus:after,.fad.fa-comment-plus:after{content:"\f4b2\f4b2"}.fa-duotone.fa-triangle-instrument:after,.fa-duotone.fa-triangle-music:after,.fad.fa-triangle-instrument:after,.fad.fa-triangle-music:after{content:"\f8e2\f8e2"}.fa-duotone.fa-wheelchair:after,.fad.fa-wheelchair:after{content:"\f193\f193"}.fa-duotone.fa-user-pilot-tie:after,.fad.fa-user-pilot-tie:after{content:"\e2c1\e2c1"}.fa-duotone.fa-piano-keyboard:after,.fad.fa-piano-keyboard:after{content:"\f8d5\f8d5"}.fa-duotone.fa-bed-empty:after,.fad.fa-bed-empty:after{content:"\f8f9\f8f9"}.fa-duotone.fa-arrow-circle-up:after,.fa-duotone.fa-circle-arrow-up:after,.fad.fa-arrow-circle-up:after,.fad.fa-circle-arrow-up:after{content:"\f0aa\f0aa"}.fa-duotone.fa-toggle-on:after,.fad.fa-toggle-on:after{content:"\f205\f205"}.fa-duotone.fa-rectangle-portrait:after,.fa-duotone.fa-rectangle-vertical:after,.fad.fa-rectangle-portrait:after,.fad.fa-rectangle-vertical:after{content:"\f2fb\f2fb"}.fa-duotone.fa-person-walking:after,.fa-duotone.fa-walking:after,.fad.fa-person-walking:after,.fad.fa-walking:after{content:"\f554\f554"}.fa-duotone.fa-l:after,.fad.fa-l:after{content:"\4c\4c"}.fa-duotone.fa-signal-stream:after,.fad.fa-signal-stream:after{content:"\f8dd\f8dd"}.fa-duotone.fa-down-to-bracket:after,.fad.fa-down-to-bracket:after{content:"\e4e7\e4e7"}.fa-duotone.fa-circle-z:after,.fad.fa-circle-z:after{content:"\e130\e130"}.fa-duotone.fa-stars:after,.fad.fa-stars:after{content:"\f762\f762"}.fa-duotone.fa-fire:after,.fad.fa-fire:after{content:"\f06d\f06d"}.fa-duotone.fa-bed-pulse:after,.fa-duotone.fa-procedures:after,.fad.fa-bed-pulse:after,.fad.fa-procedures:after{content:"\f487\f487"}.fa-duotone.fa-house-day:after,.fad.fa-house-day:after{content:"\e00e\e00e"}.fa-duotone.fa-shuttle-space:after,.fa-duotone.fa-space-shuttle:after,.fad.fa-shuttle-space:after,.fad.fa-space-shuttle:after{content:"\f197\f197"}.fa-duotone.fa-shirt-long-sleeve:after,.fad.fa-shirt-long-sleeve:after{content:"\e3c7\e3c7"}.fa-duotone.fa-chart-pie-alt:after,.fa-duotone.fa-chart-pie-simple:after,.fad.fa-chart-pie-alt:after,.fad.fa-chart-pie-simple:after{content:"\f64e\f64e"}.fa-duotone.fa-face-laugh:after,.fa-duotone.fa-laugh:after,.fad.fa-face-laugh:after,.fad.fa-laugh:after{content:"\f599\f599"}.fa-duotone.fa-folder-open:after,.fad.fa-folder-open:after{content:"\f07c\f07c"}.fa-duotone.fa-album-collection-circle-user:after,.fad.fa-album-collection-circle-user:after{content:"\e48f\e48f"}.fa-duotone.fa-candy:after,.fad.fa-candy:after{content:"\e3e7\e3e7"}.fa-duotone.fa-bowl-hot:after,.fa-duotone.fa-soup:after,.fad.fa-bowl-hot:after,.fad.fa-soup:after{content:"\f823\f823"}.fa-duotone.fa-flatbread:after,.fad.fa-flatbread:after{content:"\e40b\e40b"}.fa-duotone.fa-heart-circle-plus:after,.fad.fa-heart-circle-plus:after{content:"\e500\e500"}.fa-duotone.fa-code-fork:after,.fad.fa-code-fork:after{content:"\e13b\e13b"}.fa-duotone.fa-city:after,.fad.fa-city:after{content:"\f64f\f64f"}.fa-duotone.fa-signal-alt-1:after,.fa-duotone.fa-signal-bars-weak:after,.fad.fa-signal-alt-1:after,.fad.fa-signal-bars-weak:after{content:"\f691\f691"}.fa-duotone.fa-microphone-alt:after,.fa-duotone.fa-microphone-lines:after,.fad.fa-microphone-alt:after,.fad.fa-microphone-lines:after{content:"\f3c9\f3c9"}.fa-duotone.fa-clock-twelve:after,.fad.fa-clock-twelve:after{content:"\e358\e358"}.fa-duotone.fa-pepper-hot:after,.fad.fa-pepper-hot:after{content:"\f816\f816"}.fa-duotone.fa-citrus-slice:after,.fad.fa-citrus-slice:after{content:"\e2f5\e2f5"}.fa-duotone.fa-sheep:after,.fad.fa-sheep:after{content:"\f711\f711"}.fa-duotone.fa-unlock:after,.fad.fa-unlock:after{content:"\f09c\f09c"}.fa-duotone.fa-colon-sign:after,.fad.fa-colon-sign:after{content:"\e140\e140"}.fa-duotone.fa-headset:after,.fad.fa-headset:after{content:"\f590\f590"}.fa-duotone.fa-badger-honey:after,.fad.fa-badger-honey:after{content:"\f6b4\f6b4"}.fa-duotone.fa-h4:after,.fad.fa-h4:after{content:"\f86a\f86a"}.fa-duotone.fa-store-slash:after,.fad.fa-store-slash:after{content:"\e071\e071"}.fa-duotone.fa-road-circle-xmark:after,.fad.fa-road-circle-xmark:after{content:"\e566\e566"}.fa-duotone.fa-signal-slash:after,.fad.fa-signal-slash:after{content:"\f695\f695"}.fa-duotone.fa-user-minus:after,.fad.fa-user-minus:after{content:"\f503\f503"}.fa-duotone.fa-mars-stroke-up:after,.fa-duotone.fa-mars-stroke-v:after,.fad.fa-mars-stroke-up:after,.fad.fa-mars-stroke-v:after{content:"\f22a\f22a"}.fa-duotone.fa-champagne-glasses:after,.fa-duotone.fa-glass-cheers:after,.fad.fa-champagne-glasses:after,.fad.fa-glass-cheers:after{content:"\f79f\f79f"}.fa-duotone.fa-taco:after,.fad.fa-taco:after{content:"\f826\f826"}.fa-duotone.fa-hexagon-plus:after,.fa-duotone.fa-plus-hexagon:after,.fad.fa-hexagon-plus:after,.fad.fa-plus-hexagon:after{content:"\f300\f300"}.fa-duotone.fa-clipboard:after,.fad.fa-clipboard:after{content:"\f328\f328"}.fa-duotone.fa-house-circle-exclamation:after,.fad.fa-house-circle-exclamation:after{content:"\e50a\e50a"}.fa-duotone.fa-file-arrow-up:after,.fa-duotone.fa-file-upload:after,.fad.fa-file-arrow-up:after,.fad.fa-file-upload:after{content:"\f574\f574"}.fa-duotone.fa-wifi-3:after,.fa-duotone.fa-wifi-strong:after,.fa-duotone.fa-wifi:after,.fad.fa-wifi-3:after,.fad.fa-wifi-strong:after,.fad.fa-wifi:after{content:"\f1eb\f1eb"}.fa-duotone.fa-comments-alt:after,.fa-duotone.fa-messages:after,.fad.fa-comments-alt:after,.fad.fa-messages:after{content:"\f4b6\f4b6"}.fa-duotone.fa-bath:after,.fa-duotone.fa-bathtub:after,.fad.fa-bath:after,.fad.fa-bathtub:after{content:"\f2cd\f2cd"}.fa-duotone.fa-umbrella-alt:after,.fa-duotone.fa-umbrella-simple:after,.fad.fa-umbrella-alt:after,.fad.fa-umbrella-simple:after{content:"\e2bc\e2bc"}.fa-duotone.fa-rectangle-history-circle-plus:after,.fad.fa-rectangle-history-circle-plus:after{content:"\e4a3\e4a3"}.fa-duotone.fa-underline:after,.fad.fa-underline:after{content:"\f0cd\f0cd"}.fa-duotone.fa-prescription-bottle-pill:after,.fad.fa-prescription-bottle-pill:after{content:"\e5c0\e5c0"}.fa-duotone.fa-user-edit:after,.fa-duotone.fa-user-pen:after,.fad.fa-user-edit:after,.fad.fa-user-pen:after{content:"\f4ff\f4ff"}.fa-duotone.fa-binary-slash:after,.fad.fa-binary-slash:after{content:"\e33e\e33e"}.fa-duotone.fa-square-o:after,.fad.fa-square-o:after{content:"\e278\e278"}.fa-duotone.fa-signature:after,.fad.fa-signature:after{content:"\f5b7\f5b7"}.fa-duotone.fa-stroopwafel:after,.fad.fa-stroopwafel:after{content:"\f551\f551"}.fa-duotone.fa-bold:after,.fad.fa-bold:after{content:"\f032\f032"}.fa-duotone.fa-anchor-lock:after,.fad.fa-anchor-lock:after{content:"\e4ad\e4ad"}.fa-duotone.fa-building-ngo:after,.fad.fa-building-ngo:after{content:"\e4d7\e4d7"}.fa-duotone.fa-transporter-3:after,.fad.fa-transporter-3:after{content:"\e045\e045"}.fa-duotone.fa-engine-exclamation:after,.fa-duotone.fa-engine-warning:after,.fad.fa-engine-exclamation:after,.fad.fa-engine-warning:after{content:"\f5f2\f5f2"}.fa-duotone.fa-circle-down-right:after,.fad.fa-circle-down-right:after{content:"\e108\e108"}.fa-duotone.fa-square-k:after,.fad.fa-square-k:after{content:"\e274\e274"}.fa-duotone.fa-manat-sign:after,.fad.fa-manat-sign:after{content:"\e1d5\e1d5"}.fa-duotone.fa-money-check-edit:after,.fa-duotone.fa-money-check-pen:after,.fad.fa-money-check-edit:after,.fad.fa-money-check-pen:after{content:"\f872\f872"}.fa-duotone.fa-not-equal:after,.fad.fa-not-equal:after{content:"\f53e\f53e"}.fa-duotone.fa-border-style:after,.fa-duotone.fa-border-top-left:after,.fad.fa-border-style:after,.fad.fa-border-top-left:after{content:"\f853\f853"}.fa-duotone.fa-map-location-dot:after,.fa-duotone.fa-map-marked-alt:after,.fad.fa-map-location-dot:after,.fad.fa-map-marked-alt:after{content:"\f5a0\f5a0"}.fa-duotone.fa-tilde:after,.fad.fa-tilde:after{content:"\7e\7e"}.fa-duotone.fa-jedi:after,.fad.fa-jedi:after{content:"\f669\f669"}.fa-duotone.fa-poll:after,.fa-duotone.fa-square-poll-vertical:after,.fad.fa-poll:after,.fad.fa-square-poll-vertical:after{content:"\f681\f681"}.fa-duotone.fa-arrow-down-square-triangle:after,.fa-duotone.fa-sort-shapes-down-alt:after,.fad.fa-arrow-down-square-triangle:after,.fad.fa-sort-shapes-down-alt:after{content:"\f889\f889"}.fa-duotone.fa-mug-hot:after,.fad.fa-mug-hot:after{content:"\f7b6\f7b6"}.fa-duotone.fa-dog-leashed:after,.fad.fa-dog-leashed:after{content:"\f6d4\f6d4"}.fa-duotone.fa-battery-car:after,.fa-duotone.fa-car-battery:after,.fad.fa-battery-car:after,.fad.fa-car-battery:after{content:"\f5df\f5df"}.fa-duotone.fa-face-downcast-sweat:after,.fad.fa-face-downcast-sweat:after{content:"\e371\e371"}.fa-duotone.fa-mailbox-flag-up:after,.fad.fa-mailbox-flag-up:after{content:"\e5bb\e5bb"}.fa-duotone.fa-memo-circle-info:after,.fad.fa-memo-circle-info:after{content:"\e49a\e49a"}.fa-duotone.fa-gift:after,.fad.fa-gift:after{content:"\f06b\f06b"}.fa-duotone.fa-dice-two:after,.fad.fa-dice-two:after{content:"\f528\f528"}.fa-duotone.fa-volume-medium:after,.fa-duotone.fa-volume:after,.fad.fa-volume-medium:after,.fad.fa-volume:after{content:"\f6a8\f6a8"}.fa-duotone.fa-transporter-5:after,.fad.fa-transporter-5:after{content:"\e2a6\e2a6"}.fa-duotone.fa-gauge-circle-bolt:after,.fad.fa-gauge-circle-bolt:after{content:"\e496\e496"}.fa-duotone.fa-coin-front:after,.fad.fa-coin-front:after{content:"\e3fc\e3fc"}.fa-duotone.fa-file-slash:after,.fad.fa-file-slash:after{content:"\e3a7\e3a7"}.fa-duotone.fa-message-arrow-up-right:after,.fad.fa-message-arrow-up-right:after{content:"\e1dd\e1dd"}.fa-duotone.fa-treasure-chest:after,.fad.fa-treasure-chest:after{content:"\f723\f723"}.fa-duotone.fa-chess-queen:after,.fad.fa-chess-queen:after{content:"\f445\f445"}.fa-duotone.fa-paint-brush-alt:after,.fa-duotone.fa-paint-brush-fine:after,.fa-duotone.fa-paintbrush-alt:after,.fa-duotone.fa-paintbrush-fine:after,.fad.fa-paint-brush-alt:after,.fad.fa-paint-brush-fine:after,.fad.fa-paintbrush-alt:after,.fad.fa-paintbrush-fine:after{content:"\f5a9\f5a9"}.fa-duotone.fa-glasses:after,.fad.fa-glasses:after{content:"\f530\f530"}.fa-duotone.fa-hood-cloak:after,.fad.fa-hood-cloak:after{content:"\f6ef\f6ef"}.fa-duotone.fa-square-quote:after,.fad.fa-square-quote:after{content:"\e329\e329"}.fa-duotone.fa-up-left:after,.fad.fa-up-left:after{content:"\e2bd\e2bd"}.fa-duotone.fa-bring-front:after,.fad.fa-bring-front:after{content:"\f857\f857"}.fa-duotone.fa-chess-board:after,.fad.fa-chess-board:after{content:"\f43c\f43c"}.fa-duotone.fa-burger-cheese:after,.fa-duotone.fa-cheeseburger:after,.fad.fa-burger-cheese:after,.fad.fa-cheeseburger:after{content:"\f7f1\f7f1"}.fa-duotone.fa-building-circle-check:after,.fad.fa-building-circle-check:after{content:"\e4d2\e4d2"}.fa-duotone.fa-repeat-1:after,.fad.fa-repeat-1:after{content:"\f365\f365"}.fa-duotone.fa-arrow-down-to-line:after,.fa-duotone.fa-arrow-to-bottom:after,.fad.fa-arrow-down-to-line:after,.fad.fa-arrow-to-bottom:after{content:"\f33d\f33d"}.fa-duotone.fa-grid-5:after,.fad.fa-grid-5:after{content:"\e199\e199"}.fa-duotone.fa-swap-arrows:after,.fad.fa-swap-arrows:after{content:"\e60a\e60a"}.fa-duotone.fa-right-long-to-line:after,.fad.fa-right-long-to-line:after{content:"\e444\e444"}.fa-duotone.fa-person-chalkboard:after,.fad.fa-person-chalkboard:after{content:"\e53d\e53d"}.fa-duotone.fa-mars-stroke-h:after,.fa-duotone.fa-mars-stroke-right:after,.fad.fa-mars-stroke-h:after,.fad.fa-mars-stroke-right:after{content:"\f22b\f22b"}.fa-duotone.fa-hand-back-fist:after,.fa-duotone.fa-hand-rock:after,.fad.fa-hand-back-fist:after,.fad.fa-hand-rock:after{content:"\f255\f255"}.fa-duotone.fa-grid-round-5:after,.fad.fa-grid-round-5:after{content:"\e5de\e5de"}.fa-duotone.fa-tally-5:after,.fa-duotone.fa-tally:after,.fad.fa-tally-5:after,.fad.fa-tally:after{content:"\f69c\f69c"}.fa-duotone.fa-caret-square-up:after,.fa-duotone.fa-square-caret-up:after,.fad.fa-caret-square-up:after,.fad.fa-square-caret-up:after{content:"\f151\f151"}.fa-duotone.fa-cloud-showers-water:after,.fad.fa-cloud-showers-water:after{content:"\e4e4\e4e4"}.fa-duotone.fa-bar-chart:after,.fa-duotone.fa-chart-bar:after,.fad.fa-bar-chart:after,.fad.fa-chart-bar:after{content:"\f080\f080"}.fa-duotone.fa-hands-bubbles:after,.fa-duotone.fa-hands-wash:after,.fad.fa-hands-bubbles:after,.fad.fa-hands-wash:after{content:"\e05e\e05e"}.fa-duotone.fa-less-than-equal:after,.fad.fa-less-than-equal:after{content:"\f537\f537"}.fa-duotone.fa-train:after,.fad.fa-train:after{content:"\f238\f238"}.fa-duotone.fa-up-from-dotted-line:after,.fad.fa-up-from-dotted-line:after{content:"\e456\e456"}.fa-duotone.fa-eye-low-vision:after,.fa-duotone.fa-low-vision:after,.fad.fa-eye-low-vision:after,.fad.fa-low-vision:after{content:"\f2a8\f2a8"}.fa-duotone.fa-traffic-light-go:after,.fad.fa-traffic-light-go:after{content:"\f638\f638"}.fa-duotone.fa-face-exhaling:after,.fad.fa-face-exhaling:after{content:"\e480\e480"}.fa-duotone.fa-sensor-fire:after,.fad.fa-sensor-fire:after{content:"\e02a\e02a"}.fa-duotone.fa-user-unlock:after,.fad.fa-user-unlock:after{content:"\e058\e058"}.fa-duotone.fa-hexagon-divide:after,.fad.fa-hexagon-divide:after{content:"\e1ad\e1ad"}.fa-duotone.fa-00:after,.fad.fa-00:after{content:"\e467\e467"}.fa-duotone.fa-crow:after,.fad.fa-crow:after{content:"\f520\f520"}.fa-duotone.fa-betamax:after,.fa-duotone.fa-cassette-betamax:after,.fad.fa-betamax:after,.fad.fa-cassette-betamax:after{content:"\f8a4\f8a4"}.fa-duotone.fa-sailboat:after,.fad.fa-sailboat:after{content:"\e445\e445"}.fa-duotone.fa-window-restore:after,.fad.fa-window-restore:after{content:"\f2d2\f2d2"}.fa-duotone.fa-nfc-magnifying-glass:after,.fad.fa-nfc-magnifying-glass:after{content:"\e1f9\e1f9"}.fa-duotone.fa-file-binary:after,.fad.fa-file-binary:after{content:"\e175\e175"}.fa-duotone.fa-circle-v:after,.fad.fa-circle-v:after{content:"\e12a\e12a"}.fa-duotone.fa-plus-square:after,.fa-duotone.fa-square-plus:after,.fad.fa-plus-square:after,.fad.fa-square-plus:after{content:"\f0fe\f0fe"}.fa-duotone.fa-bowl-scoops:after,.fad.fa-bowl-scoops:after{content:"\e3df\e3df"}.fa-duotone.fa-mistletoe:after,.fad.fa-mistletoe:after{content:"\f7b4\f7b4"}.fa-duotone.fa-custard:after,.fad.fa-custard:after{content:"\e403\e403"}.fa-duotone.fa-lacrosse-stick:after,.fad.fa-lacrosse-stick:after{content:"\e3b5\e3b5"}.fa-duotone.fa-hockey-mask:after,.fad.fa-hockey-mask:after{content:"\f6ee\f6ee"}.fa-duotone.fa-sunrise:after,.fad.fa-sunrise:after{content:"\f766\f766"}.fa-duotone.fa-subtitles:after,.fad.fa-subtitles:after{content:"\e60f\e60f"}.fa-duotone.fa-panel-ews:after,.fad.fa-panel-ews:after{content:"\e42e\e42e"}.fa-duotone.fa-torii-gate:after,.fad.fa-torii-gate:after{content:"\f6a1\f6a1"}.fa-duotone.fa-cloud-exclamation:after,.fad.fa-cloud-exclamation:after{content:"\e491\e491"}.fa-duotone.fa-comment-alt-lines:after,.fa-duotone.fa-message-lines:after,.fad.fa-comment-alt-lines:after,.fad.fa-message-lines:after{content:"\f4a6\f4a6"}.fa-duotone.fa-frog:after,.fad.fa-frog:after{content:"\f52e\f52e"}.fa-duotone.fa-bucket:after,.fad.fa-bucket:after{content:"\e4cf\e4cf"}.fa-duotone.fa-floppy-disk-pen:after,.fad.fa-floppy-disk-pen:after{content:"\e182\e182"}.fa-duotone.fa-image:after,.fad.fa-image:after{content:"\f03e\f03e"}.fa-duotone.fa-window-frame:after,.fad.fa-window-frame:after{content:"\e04f\e04f"}.fa-duotone.fa-microphone:after,.fad.fa-microphone:after{content:"\f130\f130"}.fa-duotone.fa-cow:after,.fad.fa-cow:after{content:"\f6c8\f6c8"}.fa-duotone.fa-file-zip:after,.fad.fa-file-zip:after{content:"\e5ee\e5ee"}.fa-duotone.fa-square-ring:after,.fad.fa-square-ring:after{content:"\e44f\e44f"}.fa-duotone.fa-arrow-alt-from-top:after,.fa-duotone.fa-down-from-line:after,.fad.fa-arrow-alt-from-top:after,.fad.fa-down-from-line:after{content:"\f349\f349"}.fa-duotone.fa-caret-up:after,.fad.fa-caret-up:after{content:"\f0d8\f0d8"}.fa-duotone.fa-shield-times:after,.fa-duotone.fa-shield-xmark:after,.fad.fa-shield-times:after,.fad.fa-shield-xmark:after{content:"\e24c\e24c"}.fa-duotone.fa-screwdriver:after,.fad.fa-screwdriver:after{content:"\f54a\f54a"}.fa-duotone.fa-circle-sort-down:after,.fa-duotone.fa-sort-circle-down:after,.fad.fa-circle-sort-down:after,.fad.fa-sort-circle-down:after{content:"\e031\e031"}.fa-duotone.fa-folder-closed:after,.fad.fa-folder-closed:after{content:"\e185\e185"}.fa-duotone.fa-house-tsunami:after,.fad.fa-house-tsunami:after{content:"\e515\e515"}.fa-duotone.fa-square-nfi:after,.fad.fa-square-nfi:after{content:"\e576\e576"}.fa-duotone.fa-forklift:after,.fad.fa-forklift:after{content:"\f47a\f47a"}.fa-duotone.fa-arrow-up-from-ground-water:after,.fad.fa-arrow-up-from-ground-water:after{content:"\e4b5\e4b5"}.fa-duotone.fa-bracket-square-right:after,.fad.fa-bracket-square-right:after{content:"\5d\5d"}.fa-duotone.fa-glass-martini-alt:after,.fa-duotone.fa-martini-glass:after,.fad.fa-glass-martini-alt:after,.fad.fa-martini-glass:after{content:"\f57b\f57b"}.fa-duotone.fa-rotate-back:after,.fa-duotone.fa-rotate-backward:after,.fa-duotone.fa-rotate-left:after,.fa-duotone.fa-undo-alt:after,.fad.fa-rotate-back:after,.fad.fa-rotate-backward:after,.fad.fa-rotate-left:after,.fad.fa-undo-alt:after{content:"\f2ea\f2ea"}.fa-duotone.fa-columns:after,.fa-duotone.fa-table-columns:after,.fad.fa-columns:after,.fad.fa-table-columns:after{content:"\f0db\f0db"}.fa-duotone.fa-square-a:after,.fad.fa-square-a:after{content:"\e25f\e25f"}.fa-duotone.fa-tick:after,.fad.fa-tick:after{content:"\e32f\e32f"}.fa-duotone.fa-lemon:after,.fad.fa-lemon:after{content:"\f094\f094"}.fa-duotone.fa-head-side-mask:after,.fad.fa-head-side-mask:after{content:"\e063\e063"}.fa-duotone.fa-handshake:after,.fad.fa-handshake:after{content:"\f2b5\f2b5"}.fa-duotone.fa-gem:after,.fad.fa-gem:after{content:"\f3a5\f3a5"}.fa-duotone.fa-dolly-box:after,.fa-duotone.fa-dolly:after,.fad.fa-dolly-box:after,.fad.fa-dolly:after{content:"\f472\f472"}.fa-duotone.fa-smoking:after,.fad.fa-smoking:after{content:"\f48d\f48d"}.fa-duotone.fa-compress-arrows-alt:after,.fa-duotone.fa-minimize:after,.fad.fa-compress-arrows-alt:after,.fad.fa-minimize:after{content:"\f78c\f78c"}.fa-duotone.fa-refrigerator:after,.fad.fa-refrigerator:after{content:"\e026\e026"}.fa-duotone.fa-monument:after,.fad.fa-monument:after{content:"\f5a6\f5a6"}.fa-duotone.fa-octagon-xmark:after,.fa-duotone.fa-times-octagon:after,.fa-duotone.fa-xmark-octagon:after,.fad.fa-octagon-xmark:after,.fad.fa-times-octagon:after,.fad.fa-xmark-octagon:after{content:"\f2f0\f2f0"}.fa-duotone.fa-align-slash:after,.fad.fa-align-slash:after{content:"\f846\f846"}.fa-duotone.fa-snowplow:after,.fad.fa-snowplow:after{content:"\f7d2\f7d2"}.fa-duotone.fa-angle-double-right:after,.fa-duotone.fa-angles-right:after,.fad.fa-angle-double-right:after,.fad.fa-angles-right:after{content:"\f101\f101"}.fa-duotone.fa-truck-couch:after,.fa-duotone.fa-truck-ramp-couch:after,.fad.fa-truck-couch:after,.fad.fa-truck-ramp-couch:after{content:"\f4dd\f4dd"}.fa-duotone.fa-cannabis:after,.fad.fa-cannabis:after{content:"\f55f\f55f"}.fa-duotone.fa-circle-play:after,.fa-duotone.fa-play-circle:after,.fad.fa-circle-play:after,.fad.fa-play-circle:after{content:"\f144\f144"}.fa-duotone.fa-arrow-up-right-and-arrow-down-left-from-center:after,.fad.fa-arrow-up-right-and-arrow-down-left-from-center:after{content:"\e0a0\e0a0"}.fa-duotone.fa-tablets:after,.fad.fa-tablets:after{content:"\f490\f490"}.fa-duotone.fa-360-degrees:after,.fad.fa-360-degrees:after{content:"\e2dc\e2dc"}.fa-duotone.fa-ethernet:after,.fad.fa-ethernet:after{content:"\f796\f796"}.fa-duotone.fa-eur:after,.fa-duotone.fa-euro-sign:after,.fa-duotone.fa-euro:after,.fad.fa-eur:after,.fad.fa-euro-sign:after,.fad.fa-euro:after{content:"\f153\f153"}.fa-duotone.fa-chair:after,.fad.fa-chair:after{content:"\f6c0\f6c0"}.fa-duotone.fa-check-circle:after,.fa-duotone.fa-circle-check:after,.fad.fa-check-circle:after,.fad.fa-circle-check:after{content:"\f058\f058"}.fa-duotone.fa-square-dashed-circle-plus:after,.fad.fa-square-dashed-circle-plus:after{content:"\e5c2\e5c2"}.fa-duotone.fa-money-simple-from-bracket:after,.fad.fa-money-simple-from-bracket:after{content:"\e313\e313"}.fa-duotone.fa-bat:after,.fad.fa-bat:after{content:"\f6b5\f6b5"}.fa-duotone.fa-circle-stop:after,.fa-duotone.fa-stop-circle:after,.fad.fa-circle-stop:after,.fad.fa-stop-circle:after{content:"\f28d\f28d"}.fa-duotone.fa-head-side-headphones:after,.fad.fa-head-side-headphones:after{content:"\f8c2\f8c2"}.fa-duotone.fa-phone-rotary:after,.fad.fa-phone-rotary:after{content:"\f8d3\f8d3"}.fa-duotone.fa-compass-drafting:after,.fa-duotone.fa-drafting-compass:after,.fad.fa-compass-drafting:after,.fad.fa-drafting-compass:after{content:"\f568\f568"}.fa-duotone.fa-plate-wheat:after,.fad.fa-plate-wheat:after{content:"\e55a\e55a"}.fa-duotone.fa-calendar-circle-minus:after,.fad.fa-calendar-circle-minus:after{content:"\e46f\e46f"}.fa-duotone.fa-chopsticks:after,.fad.fa-chopsticks:after{content:"\e3f7\e3f7"}.fa-duotone.fa-car-mechanic:after,.fa-duotone.fa-car-wrench:after,.fad.fa-car-mechanic:after,.fad.fa-car-wrench:after{content:"\f5e3\f5e3"}.fa-duotone.fa-icicles:after,.fad.fa-icicles:after{content:"\f7ad\f7ad"}.fa-duotone.fa-person-shelter:after,.fad.fa-person-shelter:after{content:"\e54f\e54f"}.fa-duotone.fa-neuter:after,.fad.fa-neuter:after{content:"\f22c\f22c"}.fa-duotone.fa-id-badge:after,.fad.fa-id-badge:after{content:"\f2c1\f2c1"}.fa-duotone.fa-kazoo:after,.fad.fa-kazoo:after{content:"\f8c7\f8c7"}.fa-duotone.fa-marker:after,.fad.fa-marker:after{content:"\f5a1\f5a1"}.fa-duotone.fa-bin-bottles:after,.fad.fa-bin-bottles:after{content:"\e5f5\e5f5"}.fa-duotone.fa-face-laugh-beam:after,.fa-duotone.fa-laugh-beam:after,.fad.fa-face-laugh-beam:after,.fad.fa-laugh-beam:after{content:"\f59a\f59a"}.fa-duotone.fa-square-arrow-down-left:after,.fad.fa-square-arrow-down-left:after{content:"\e261\e261"}.fa-duotone.fa-battery-bolt:after,.fad.fa-battery-bolt:after{content:"\f376\f376"}.fa-duotone.fa-tree-large:after,.fad.fa-tree-large:after{content:"\f7dd\f7dd"}.fa-duotone.fa-helicopter-symbol:after,.fad.fa-helicopter-symbol:after{content:"\e502\e502"}.fa-duotone.fa-aperture:after,.fad.fa-aperture:after{content:"\e2df\e2df"}.fa-duotone.fa-universal-access:after,.fad.fa-universal-access:after{content:"\f29a\f29a"}.fa-duotone.fa-gear-complex:after,.fad.fa-gear-complex:after{content:"\e5e9\e5e9"}.fa-duotone.fa-file-magnifying-glass:after,.fa-duotone.fa-file-search:after,.fad.fa-file-magnifying-glass:after,.fad.fa-file-search:after{content:"\f865\f865"}.fa-duotone.fa-up-right:after,.fad.fa-up-right:after{content:"\e2be\e2be"}.fa-duotone.fa-chevron-circle-up:after,.fa-duotone.fa-circle-chevron-up:after,.fad.fa-chevron-circle-up:after,.fad.fa-circle-chevron-up:after{content:"\f139\f139"}.fa-duotone.fa-user-police:after,.fad.fa-user-police:after{content:"\e333\e333"}.fa-duotone.fa-lari-sign:after,.fad.fa-lari-sign:after{content:"\e1c8\e1c8"}.fa-duotone.fa-volcano:after,.fad.fa-volcano:after{content:"\f770\f770"}.fa-duotone.fa-teddy-bear:after,.fad.fa-teddy-bear:after{content:"\e3cf\e3cf"}.fa-duotone.fa-stocking:after,.fad.fa-stocking:after{content:"\f7d5\f7d5"}.fa-duotone.fa-person-walking-dashed-line-arrow-right:after,.fad.fa-person-walking-dashed-line-arrow-right:after{content:"\e553\e553"}.fa-duotone.fa-image-slash:after,.fad.fa-image-slash:after{content:"\e1b7\e1b7"}.fa-duotone.fa-mask-snorkel:after,.fad.fa-mask-snorkel:after{content:"\e3b7\e3b7"}.fa-duotone.fa-smoke:after,.fad.fa-smoke:after{content:"\f760\f760"}.fa-duotone.fa-gbp:after,.fa-duotone.fa-pound-sign:after,.fa-duotone.fa-sterling-sign:after,.fad.fa-gbp:after,.fad.fa-pound-sign:after,.fad.fa-sterling-sign:after{content:"\f154\f154"}.fa-duotone.fa-battery-exclamation:after,.fad.fa-battery-exclamation:after{content:"\e0b0\e0b0"}.fa-duotone.fa-viruses:after,.fad.fa-viruses:after{content:"\e076\e076"}.fa-duotone.fa-square-person-confined:after,.fad.fa-square-person-confined:after{content:"\e577\e577"}.fa-duotone.fa-user-tie:after,.fad.fa-user-tie:after{content:"\f508\f508"}.fa-duotone.fa-arrow-down-long:after,.fa-duotone.fa-long-arrow-down:after,.fad.fa-arrow-down-long:after,.fad.fa-long-arrow-down:after{content:"\f175\f175"}.fa-duotone.fa-tent-arrow-down-to-line:after,.fad.fa-tent-arrow-down-to-line:after{content:"\e57e\e57e"}.fa-duotone.fa-certificate:after,.fad.fa-certificate:after{content:"\f0a3\f0a3"}.fa-duotone.fa-crystal-ball:after,.fad.fa-crystal-ball:after{content:"\e362\e362"}.fa-duotone.fa-mail-reply-all:after,.fa-duotone.fa-reply-all:after,.fad.fa-mail-reply-all:after,.fad.fa-reply-all:after{content:"\f122\f122"}.fa-duotone.fa-suitcase:after,.fad.fa-suitcase:after{content:"\f0f2\f0f2"}.fa-duotone.fa-person-skating:after,.fa-duotone.fa-skating:after,.fad.fa-person-skating:after,.fad.fa-skating:after{content:"\f7c5\f7c5"}.fa-duotone.fa-star-shooting:after,.fad.fa-star-shooting:after{content:"\e036\e036"}.fa-duotone.fa-binary-lock:after,.fad.fa-binary-lock:after{content:"\e33d\e33d"}.fa-duotone.fa-filter-circle-dollar:after,.fa-duotone.fa-funnel-dollar:after,.fad.fa-filter-circle-dollar:after,.fad.fa-funnel-dollar:after{content:"\f662\f662"}.fa-duotone.fa-camera-retro:after,.fad.fa-camera-retro:after{content:"\f083\f083"}.fa-duotone.fa-arrow-circle-down:after,.fa-duotone.fa-circle-arrow-down:after,.fad.fa-arrow-circle-down:after,.fad.fa-circle-arrow-down:after{content:"\f0ab\f0ab"}.fa-duotone.fa-comment-edit:after,.fa-duotone.fa-comment-pen:after,.fad.fa-comment-edit:after,.fad.fa-comment-pen:after{content:"\f4ae\f4ae"}.fa-duotone.fa-arrow-right-to-file:after,.fa-duotone.fa-file-import:after,.fad.fa-arrow-right-to-file:after,.fad.fa-file-import:after{content:"\f56f\f56f"}.fa-duotone.fa-banjo:after,.fad.fa-banjo:after{content:"\f8a3\f8a3"}.fa-duotone.fa-external-link-square:after,.fa-duotone.fa-square-arrow-up-right:after,.fad.fa-external-link-square:after,.fad.fa-square-arrow-up-right:after{content:"\f14c\f14c"}.fa-duotone.fa-light-emergency-on:after,.fad.fa-light-emergency-on:after{content:"\e420\e420"}.fa-duotone.fa-kerning:after,.fad.fa-kerning:after{content:"\f86f\f86f"}.fa-duotone.fa-box-open:after,.fad.fa-box-open:after{content:"\f49e\f49e"}.fa-duotone.fa-square-f:after,.fad.fa-square-f:after{content:"\e270\e270"}.fa-duotone.fa-scroll:after,.fad.fa-scroll:after{content:"\f70e\f70e"}.fa-duotone.fa-spa:after,.fad.fa-spa:after{content:"\f5bb\f5bb"}.fa-duotone.fa-arrow-from-right:after,.fa-duotone.fa-arrow-left-from-line:after,.fad.fa-arrow-from-right:after,.fad.fa-arrow-left-from-line:after{content:"\f344\f344"}.fa-duotone.fa-strawberry:after,.fad.fa-strawberry:after{content:"\e32b\e32b"}.fa-duotone.fa-location-pin-lock:after,.fad.fa-location-pin-lock:after{content:"\e51f\e51f"}.fa-duotone.fa-pause:after,.fad.fa-pause:after{content:"\f04c\f04c"}.fa-duotone.fa-clock-eight-thirty:after,.fad.fa-clock-eight-thirty:after{content:"\e346\e346"}.fa-duotone.fa-plane-alt:after,.fa-duotone.fa-plane-engines:after,.fad.fa-plane-alt:after,.fad.fa-plane-engines:after{content:"\f3de\f3de"}.fa-duotone.fa-hill-avalanche:after,.fad.fa-hill-avalanche:after{content:"\e507\e507"}.fa-duotone.fa-temperature-0:after,.fa-duotone.fa-temperature-empty:after,.fa-duotone.fa-thermometer-0:after,.fa-duotone.fa-thermometer-empty:after,.fad.fa-temperature-0:after,.fad.fa-temperature-empty:after,.fad.fa-thermometer-0:after,.fad.fa-thermometer-empty:after{content:"\f2cb\f2cb"}.fa-duotone.fa-bomb:after,.fad.fa-bomb:after{content:"\f1e2\f1e2"}.fa-duotone.fa-gauge-low:after,.fa-duotone.fa-tachometer-alt-slow:after,.fad.fa-gauge-low:after,.fad.fa-tachometer-alt-slow:after{content:"\f627\f627"}.fa-duotone.fa-registered:after,.fad.fa-registered:after{content:"\f25d\f25d"}.fa-duotone.fa-trash-can-plus:after,.fad.fa-trash-can-plus:after{content:"\e2ac\e2ac"}.fa-duotone.fa-address-card:after,.fa-duotone.fa-contact-card:after,.fa-duotone.fa-vcard:after,.fad.fa-address-card:after,.fad.fa-contact-card:after,.fad.fa-vcard:after{content:"\f2bb\f2bb"}.fa-duotone.fa-balance-scale-right:after,.fa-duotone.fa-scale-unbalanced-flip:after,.fad.fa-balance-scale-right:after,.fad.fa-scale-unbalanced-flip:after{content:"\f516\f516"}.fa-duotone.fa-globe-snow:after,.fad.fa-globe-snow:after{content:"\f7a3\f7a3"}.fa-duotone.fa-subscript:after,.fad.fa-subscript:after{content:"\f12c\f12c"}.fa-duotone.fa-diamond-turn-right:after,.fa-duotone.fa-directions:after,.fad.fa-diamond-turn-right:after,.fad.fa-directions:after{content:"\f5eb\f5eb"}.fa-duotone.fa-integral:after,.fad.fa-integral:after{content:"\f667\f667"}.fa-duotone.fa-burst:after,.fad.fa-burst:after{content:"\e4dc\e4dc"}.fa-duotone.fa-house-laptop:after,.fa-duotone.fa-laptop-house:after,.fad.fa-house-laptop:after,.fad.fa-laptop-house:after{content:"\e066\e066"}.fa-duotone.fa-face-tired:after,.fa-duotone.fa-tired:after,.fad.fa-face-tired:after,.fad.fa-tired:after{content:"\f5c8\f5c8"}.fa-duotone.fa-money-bills:after,.fad.fa-money-bills:after{content:"\e1f3\e1f3"}.fa-duotone.fa-blinds-raised:after,.fad.fa-blinds-raised:after{content:"\f8fd\f8fd"}.fa-duotone.fa-smog:after,.fad.fa-smog:after{content:"\f75f\f75f"}.fa-duotone.fa-ufo-beam:after,.fad.fa-ufo-beam:after{content:"\e048\e048"}.fa-duotone.fa-caret-circle-up:after,.fa-duotone.fa-circle-caret-up:after,.fad.fa-caret-circle-up:after,.fad.fa-circle-caret-up:after{content:"\f331\f331"}.fa-duotone.fa-user-vneck-hair-long:after,.fad.fa-user-vneck-hair-long:after{content:"\e463\e463"}.fa-duotone.fa-square-a-lock:after,.fad.fa-square-a-lock:after{content:"\e44d\e44d"}.fa-duotone.fa-crutch:after,.fad.fa-crutch:after{content:"\f7f7\f7f7"}.fa-duotone.fa-gas-pump-slash:after,.fad.fa-gas-pump-slash:after{content:"\f5f4\f5f4"}.fa-duotone.fa-cloud-arrow-up:after,.fa-duotone.fa-cloud-upload-alt:after,.fa-duotone.fa-cloud-upload:after,.fad.fa-cloud-arrow-up:after,.fad.fa-cloud-upload-alt:after,.fad.fa-cloud-upload:after{content:"\f0ee\f0ee"}.fa-duotone.fa-palette:after,.fad.fa-palette:after{content:"\f53f\f53f"}.fa-duotone.fa-transporter-4:after,.fad.fa-transporter-4:after{content:"\e2a5\e2a5"}.fa-duotone.fa-chart-mixed-up-circle-currency:after,.fad.fa-chart-mixed-up-circle-currency:after{content:"\e5d8\e5d8"}.fa-duotone.fa-objects-align-right:after,.fad.fa-objects-align-right:after{content:"\e3bf\e3bf"}.fa-duotone.fa-arrows-turn-right:after,.fad.fa-arrows-turn-right:after{content:"\e4c0\e4c0"}.fa-duotone.fa-vest:after,.fad.fa-vest:after{content:"\e085\e085"}.fa-duotone.fa-pig:after,.fad.fa-pig:after{content:"\f706\f706"}.fa-duotone.fa-inbox-full:after,.fad.fa-inbox-full:after{content:"\e1ba\e1ba"}.fa-duotone.fa-circle-envelope:after,.fa-duotone.fa-envelope-circle:after,.fad.fa-circle-envelope:after,.fad.fa-envelope-circle:after{content:"\e10c\e10c"}.fa-duotone.fa-construction:after,.fa-duotone.fa-triangle-person-digging:after,.fad.fa-construction:after,.fad.fa-triangle-person-digging:after{content:"\f85d\f85d"}.fa-duotone.fa-ferry:after,.fad.fa-ferry:after{content:"\e4ea\e4ea"}.fa-duotone.fa-bullseye-arrow:after,.fad.fa-bullseye-arrow:after{content:"\f648\f648"}.fa-duotone.fa-arrows-down-to-people:after,.fad.fa-arrows-down-to-people:after{content:"\e4b9\e4b9"}.fa-duotone.fa-seedling:after,.fa-duotone.fa-sprout:after,.fad.fa-seedling:after,.fad.fa-sprout:after{content:"\f4d8\f4d8"}.fa-duotone.fa-clock-seven:after,.fad.fa-clock-seven:after{content:"\e350\e350"}.fa-duotone.fa-arrows-alt-h:after,.fa-duotone.fa-left-right:after,.fad.fa-arrows-alt-h:after,.fad.fa-left-right:after{content:"\f337\f337"}.fa-duotone.fa-boxes-packing:after,.fad.fa-boxes-packing:after{content:"\e4c7\e4c7"}.fa-duotone.fa-arrow-circle-left:after,.fa-duotone.fa-circle-arrow-left:after,.fad.fa-arrow-circle-left:after,.fad.fa-circle-arrow-left:after{content:"\f0a8\f0a8"}.fa-duotone.fa-flashlight:after,.fad.fa-flashlight:after{content:"\f8b8\f8b8"}.fa-duotone.fa-group-arrows-rotate:after,.fad.fa-group-arrows-rotate:after{content:"\e4f6\e4f6"}.fa-duotone.fa-bowl-food:after,.fad.fa-bowl-food:after{content:"\e4c6\e4c6"}.fa-duotone.fa-square-9:after,.fad.fa-square-9:after{content:"\e25e\e25e"}.fa-duotone.fa-candy-cane:after,.fad.fa-candy-cane:after{content:"\f786\f786"}.fa-duotone.fa-arrow-down-wide-short:after,.fa-duotone.fa-sort-amount-asc:after,.fa-duotone.fa-sort-amount-down:after,.fad.fa-arrow-down-wide-short:after,.fad.fa-sort-amount-asc:after,.fad.fa-sort-amount-down:after{content:"\f160\f160"}.fa-duotone.fa-dollar-square:after,.fa-duotone.fa-square-dollar:after,.fa-duotone.fa-usd-square:after,.fad.fa-dollar-square:after,.fad.fa-square-dollar:after,.fad.fa-usd-square:after{content:"\f2e9\f2e9"}.fa-duotone.fa-phone-arrow-right:after,.fad.fa-phone-arrow-right:after{content:"\e5be\e5be"}.fa-duotone.fa-hand-holding-seedling:after,.fad.fa-hand-holding-seedling:after{content:"\f4bf\f4bf"}.fa-duotone.fa-comment-alt-check:after,.fa-duotone.fa-message-check:after,.fad.fa-comment-alt-check:after,.fad.fa-message-check:after{content:"\f4a2\f4a2"}.fa-duotone.fa-cloud-bolt:after,.fa-duotone.fa-thunderstorm:after,.fad.fa-cloud-bolt:after,.fad.fa-thunderstorm:after{content:"\f76c\f76c"}.fa-duotone.fa-chart-line-up-down:after,.fad.fa-chart-line-up-down:after{content:"\e5d7\e5d7"}.fa-duotone.fa-remove-format:after,.fa-duotone.fa-text-slash:after,.fad.fa-remove-format:after,.fad.fa-text-slash:after{content:"\f87d\f87d"}.fa-duotone.fa-watch:after,.fad.fa-watch:after{content:"\f2e1\f2e1"}.fa-duotone.fa-circle-down-left:after,.fad.fa-circle-down-left:after{content:"\e107\e107"}.fa-duotone.fa-text:after,.fad.fa-text:after{content:"\f893\f893"}.fa-duotone.fa-projector:after,.fad.fa-projector:after{content:"\f8d6\f8d6"}.fa-duotone.fa-face-smile-wink:after,.fa-duotone.fa-smile-wink:after,.fad.fa-face-smile-wink:after,.fad.fa-smile-wink:after{content:"\f4da\f4da"}.fa-duotone.fa-tombstone-alt:after,.fa-duotone.fa-tombstone-blank:after,.fad.fa-tombstone-alt:after,.fad.fa-tombstone-blank:after{content:"\f721\f721"}.fa-duotone.fa-chess-king-alt:after,.fa-duotone.fa-chess-king-piece:after,.fad.fa-chess-king-alt:after,.fad.fa-chess-king-piece:after{content:"\f440\f440"}.fa-duotone.fa-circle-6:after,.fad.fa-circle-6:after{content:"\e0f3\e0f3"}.fa-duotone.fa-arrow-alt-left:after,.fa-duotone.fa-left:after,.fad.fa-arrow-alt-left:after,.fad.fa-left:after{content:"\f355\f355"}.fa-duotone.fa-file-word:after,.fad.fa-file-word:after{content:"\f1c2\f1c2"}.fa-duotone.fa-file-powerpoint:after,.fad.fa-file-powerpoint:after{content:"\f1c4\f1c4"}.fa-duotone.fa-arrow-alt-square-down:after,.fa-duotone.fa-square-down:after,.fad.fa-arrow-alt-square-down:after,.fad.fa-square-down:after{content:"\f350\f350"}.fa-duotone.fa-objects-align-center-vertical:after,.fad.fa-objects-align-center-vertical:after{content:"\e3bd\e3bd"}.fa-duotone.fa-arrows-h:after,.fa-duotone.fa-arrows-left-right:after,.fad.fa-arrows-h:after,.fad.fa-arrows-left-right:after{content:"\f07e\f07e"}.fa-duotone.fa-house-lock:after,.fad.fa-house-lock:after{content:"\e510\e510"}.fa-duotone.fa-cloud-arrow-down:after,.fa-duotone.fa-cloud-download-alt:after,.fa-duotone.fa-cloud-download:after,.fad.fa-cloud-arrow-down:after,.fad.fa-cloud-download-alt:after,.fad.fa-cloud-download:after{content:"\f0ed\f0ed"}.fa-duotone.fa-wreath:after,.fad.fa-wreath:after{content:"\f7e2\f7e2"}.fa-duotone.fa-children:after,.fad.fa-children:after{content:"\e4e1\e4e1"}.fa-duotone.fa-meter-droplet:after,.fad.fa-meter-droplet:after{content:"\e1ea\e1ea"}.fa-duotone.fa-blackboard:after,.fa-duotone.fa-chalkboard:after,.fad.fa-blackboard:after,.fad.fa-chalkboard:after{content:"\f51b\f51b"}.fa-duotone.fa-user-alt-slash:after,.fa-duotone.fa-user-large-slash:after,.fad.fa-user-alt-slash:after,.fad.fa-user-large-slash:after{content:"\f4fa\f4fa"}.fa-duotone.fa-signal-4:after,.fa-duotone.fa-signal-strong:after,.fad.fa-signal-4:after,.fad.fa-signal-strong:after{content:"\f68f\f68f"}.fa-duotone.fa-lollipop:after,.fa-duotone.fa-lollypop:after,.fad.fa-lollipop:after,.fad.fa-lollypop:after{content:"\e424\e424"}.fa-duotone.fa-list-tree:after,.fad.fa-list-tree:after{content:"\e1d2\e1d2"}.fa-duotone.fa-envelope-open:after,.fad.fa-envelope-open:after{content:"\f2b6\f2b6"}.fa-duotone.fa-draw-circle:after,.fad.fa-draw-circle:after{content:"\f5ed\f5ed"}.fa-duotone.fa-cat-space:after,.fad.fa-cat-space:after{content:"\e001\e001"}.fa-duotone.fa-handshake-alt-slash:after,.fa-duotone.fa-handshake-simple-slash:after,.fad.fa-handshake-alt-slash:after,.fad.fa-handshake-simple-slash:after{content:"\e05f\e05f"}.fa-duotone.fa-rabbit-fast:after,.fa-duotone.fa-rabbit-running:after,.fad.fa-rabbit-fast:after,.fad.fa-rabbit-running:after{content:"\f709\f709"}.fa-duotone.fa-memo-pad:after,.fad.fa-memo-pad:after{content:"\e1da\e1da"}.fa-duotone.fa-mattress-pillow:after,.fad.fa-mattress-pillow:after{content:"\e525\e525"}.fa-duotone.fa-alarm-plus:after,.fad.fa-alarm-plus:after{content:"\f844\f844"}.fa-duotone.fa-alicorn:after,.fad.fa-alicorn:after{content:"\f6b0\f6b0"}.fa-duotone.fa-comment-question:after,.fad.fa-comment-question:after{content:"\e14b\e14b"}.fa-duotone.fa-gingerbread-man:after,.fad.fa-gingerbread-man:after{content:"\f79d\f79d"}.fa-duotone.fa-guarani-sign:after,.fad.fa-guarani-sign:after{content:"\e19a\e19a"}.fa-duotone.fa-burger-fries:after,.fad.fa-burger-fries:after{content:"\e0cd\e0cd"}.fa-duotone.fa-mug-tea:after,.fad.fa-mug-tea:after{content:"\f875\f875"}.fa-duotone.fa-border-top:after,.fad.fa-border-top:after{content:"\f855\f855"}.fa-duotone.fa-arrows-rotate:after,.fa-duotone.fa-refresh:after,.fa-duotone.fa-sync:after,.fad.fa-arrows-rotate:after,.fad.fa-refresh:after,.fad.fa-sync:after{content:"\f021\f021"}.fa-duotone.fa-book-circle:after,.fa-duotone.fa-circle-book-open:after,.fad.fa-book-circle:after,.fad.fa-circle-book-open:after{content:"\e0ff\e0ff"}.fa-duotone.fa-arrows-to-dotted-line:after,.fad.fa-arrows-to-dotted-line:after{content:"\e0a6\e0a6"}.fa-duotone.fa-fire-extinguisher:after,.fad.fa-fire-extinguisher:after{content:"\f134\f134"}.fa-duotone.fa-garage-open:after,.fad.fa-garage-open:after{content:"\e00b\e00b"}.fa-duotone.fa-shelves-empty:after,.fad.fa-shelves-empty:after{content:"\e246\e246"}.fa-duotone.fa-cruzeiro-sign:after,.fad.fa-cruzeiro-sign:after{content:"\e152\e152"}.fa-duotone.fa-watch-apple:after,.fad.fa-watch-apple:after{content:"\e2cb\e2cb"}.fa-duotone.fa-watch-calculator:after,.fad.fa-watch-calculator:after{content:"\f8f0\f8f0"}.fa-duotone.fa-list-dropdown:after,.fad.fa-list-dropdown:after{content:"\e1cf\e1cf"}.fa-duotone.fa-cabinet-filing:after,.fad.fa-cabinet-filing:after{content:"\f64b\f64b"}.fa-duotone.fa-burger-soda:after,.fad.fa-burger-soda:after{content:"\f858\f858"}.fa-duotone.fa-arrow-square-up:after,.fa-duotone.fa-square-arrow-up:after,.fad.fa-arrow-square-up:after,.fad.fa-square-arrow-up:after{content:"\f33c\f33c"}.fa-duotone.fa-greater-than-equal:after,.fad.fa-greater-than-equal:after{content:"\f532\f532"}.fa-duotone.fa-pallet-box:after,.fad.fa-pallet-box:after{content:"\e208\e208"}.fa-duotone.fa-face-confounded:after,.fad.fa-face-confounded:after{content:"\e36c\e36c"}.fa-duotone.fa-shield-alt:after,.fa-duotone.fa-shield-halved:after,.fad.fa-shield-alt:after,.fad.fa-shield-halved:after{content:"\f3ed\f3ed"}.fa-duotone.fa-truck-plow:after,.fad.fa-truck-plow:after{content:"\f7de\f7de"}.fa-duotone.fa-atlas:after,.fa-duotone.fa-book-atlas:after,.fad.fa-atlas:after,.fad.fa-book-atlas:after{content:"\f558\f558"}.fa-duotone.fa-virus:after,.fad.fa-virus:after{content:"\e074\e074"}.fa-duotone.fa-grid-round-2:after,.fad.fa-grid-round-2:after{content:"\e5db\e5db"}.fa-duotone.fa-comment-middle-top:after,.fad.fa-comment-middle-top:after{content:"\e14a\e14a"}.fa-duotone.fa-envelope-circle-check:after,.fad.fa-envelope-circle-check:after{content:"\e4e8\e4e8"}.fa-duotone.fa-layer-group:after,.fad.fa-layer-group:after{content:"\f5fd\f5fd"}.fa-duotone.fa-restroom-simple:after,.fad.fa-restroom-simple:after{content:"\e23a\e23a"}.fa-duotone.fa-arrows-to-dot:after,.fad.fa-arrows-to-dot:after{content:"\e4be\e4be"}.fa-duotone.fa-border-outer:after,.fad.fa-border-outer:after{content:"\f851\f851"}.fa-duotone.fa-hashtag-lock:after,.fad.fa-hashtag-lock:after{content:"\e415\e415"}.fa-duotone.fa-clock-two-thirty:after,.fad.fa-clock-two-thirty:after{content:"\e35b\e35b"}.fa-duotone.fa-archway:after,.fad.fa-archway:after{content:"\f557\f557"}.fa-duotone.fa-heart-circle-check:after,.fad.fa-heart-circle-check:after{content:"\e4fd\e4fd"}.fa-duotone.fa-house-chimney-crack:after,.fa-duotone.fa-house-damage:after,.fad.fa-house-chimney-crack:after,.fad.fa-house-damage:after{content:"\f6f1\f6f1"}.fa-duotone.fa-file-archive:after,.fa-duotone.fa-file-zipper:after,.fad.fa-file-archive:after,.fad.fa-file-zipper:after{content:"\f1c6\f1c6"}.fa-duotone.fa-heart-half:after,.fad.fa-heart-half:after{content:"\e1ab\e1ab"}.fa-duotone.fa-comment-check:after,.fad.fa-comment-check:after{content:"\f4ac\f4ac"}.fa-duotone.fa-square:after,.fad.fa-square:after{content:"\f0c8\f0c8"}.fa-duotone.fa-memo:after,.fad.fa-memo:after{content:"\e1d8\e1d8"}.fa-duotone.fa-glass-martini:after,.fa-duotone.fa-martini-glass-empty:after,.fad.fa-glass-martini:after,.fad.fa-martini-glass-empty:after{content:"\f000\f000"}.fa-duotone.fa-couch:after,.fad.fa-couch:after{content:"\f4b8\f4b8"}.fa-duotone.fa-cedi-sign:after,.fad.fa-cedi-sign:after{content:"\e0df\e0df"}.fa-duotone.fa-italic:after,.fad.fa-italic:after{content:"\f033\f033"}.fa-duotone.fa-glass-citrus:after,.fad.fa-glass-citrus:after{content:"\f869\f869"}.fa-duotone.fa-calendar-lines-pen:after,.fad.fa-calendar-lines-pen:after{content:"\e472\e472"}.fa-duotone.fa-church:after,.fad.fa-church:after{content:"\f51d\f51d"}.fa-duotone.fa-person-snowmobiling:after,.fa-duotone.fa-snowmobile:after,.fad.fa-person-snowmobiling:after,.fad.fa-snowmobile:after{content:"\f7d1\f7d1"}.fa-duotone.fa-face-hushed:after,.fad.fa-face-hushed:after{content:"\e37b\e37b"}.fa-duotone.fa-comments-dollar:after,.fad.fa-comments-dollar:after{content:"\f653\f653"}.fa-duotone.fa-pickaxe:after,.fad.fa-pickaxe:after{content:"\e5bf\e5bf"}.fa-duotone.fa-link-simple-slash:after,.fad.fa-link-simple-slash:after{content:"\e1ce\e1ce"}.fa-duotone.fa-democrat:after,.fad.fa-democrat:after{content:"\f747\f747"}.fa-duotone.fa-face-confused:after,.fad.fa-face-confused:after{content:"\e36d\e36d"}.fa-duotone.fa-pinball:after,.fad.fa-pinball:after{content:"\e229\e229"}.fa-duotone.fa-z:after,.fad.fa-z:after{content:"\5a\5a"}.fa-duotone.fa-person-skiing:after,.fa-duotone.fa-skiing:after,.fad.fa-person-skiing:after,.fad.fa-skiing:after{content:"\f7c9\f7c9"}.fa-duotone.fa-deer:after,.fad.fa-deer:after{content:"\f78e\f78e"}.fa-duotone.fa-input-pipe:after,.fad.fa-input-pipe:after{content:"\e1be\e1be"}.fa-duotone.fa-road-lock:after,.fad.fa-road-lock:after{content:"\e567\e567"}.fa-duotone.fa-a:after,.fad.fa-a:after{content:"\41\41"}.fa-duotone.fa-bookmark-slash:after,.fad.fa-bookmark-slash:after{content:"\e0c2\e0c2"}.fa-duotone.fa-temperature-arrow-down:after,.fa-duotone.fa-temperature-down:after,.fad.fa-temperature-arrow-down:after,.fad.fa-temperature-down:after{content:"\e03f\e03f"}.fa-duotone.fa-mace:after,.fad.fa-mace:after{content:"\f6f8\f6f8"}.fa-duotone.fa-feather-alt:after,.fa-duotone.fa-feather-pointed:after,.fad.fa-feather-alt:after,.fad.fa-feather-pointed:after{content:"\f56b\f56b"}.fa-duotone.fa-sausage:after,.fad.fa-sausage:after{content:"\f820\f820"}.fa-duotone.fa-trash-can-clock:after,.fad.fa-trash-can-clock:after{content:"\e2aa\e2aa"}.fa-duotone.fa-p:after,.fad.fa-p:after{content:"\50\50"}.fa-duotone.fa-broom-wide:after,.fad.fa-broom-wide:after{content:"\e5d1\e5d1"}.fa-duotone.fa-snowflake:after,.fad.fa-snowflake:after{content:"\f2dc\f2dc"}.fa-duotone.fa-stomach:after,.fad.fa-stomach:after{content:"\f623\f623"}.fa-duotone.fa-newspaper:after,.fad.fa-newspaper:after{content:"\f1ea\f1ea"}.fa-duotone.fa-ad:after,.fa-duotone.fa-rectangle-ad:after,.fad.fa-ad:after,.fad.fa-rectangle-ad:after{content:"\f641\f641"}.fa-duotone.fa-guitar-electric:after,.fad.fa-guitar-electric:after{content:"\f8be\f8be"}.fa-duotone.fa-arrow-turn-down-right:after,.fad.fa-arrow-turn-down-right:after{content:"\e3d6\e3d6"}.fa-duotone.fa-moon-cloud:after,.fad.fa-moon-cloud:after{content:"\f754\f754"}.fa-duotone.fa-bread-slice-butter:after,.fad.fa-bread-slice-butter:after{content:"\e3e1\e3e1"}.fa-duotone.fa-arrow-circle-right:after,.fa-duotone.fa-circle-arrow-right:after,.fad.fa-arrow-circle-right:after,.fad.fa-circle-arrow-right:after{content:"\f0a9\f0a9"}.fa-duotone.fa-user-group-crown:after,.fa-duotone.fa-users-crown:after,.fad.fa-user-group-crown:after,.fad.fa-users-crown:after{content:"\f6a5\f6a5"}.fa-duotone.fa-circle-i:after,.fad.fa-circle-i:after{content:"\e111\e111"}.fa-duotone.fa-toilet-paper-check:after,.fad.fa-toilet-paper-check:after{content:"\e5b2\e5b2"}.fa-duotone.fa-filter-circle-xmark:after,.fad.fa-filter-circle-xmark:after{content:"\e17b\e17b"}.fa-duotone.fa-locust:after,.fad.fa-locust:after{content:"\e520\e520"}.fa-duotone.fa-sort:after,.fa-duotone.fa-unsorted:after,.fad.fa-sort:after,.fad.fa-unsorted:after{content:"\f0dc\f0dc"}.fa-duotone.fa-list-1-2:after,.fa-duotone.fa-list-numeric:after,.fa-duotone.fa-list-ol:after,.fad.fa-list-1-2:after,.fad.fa-list-numeric:after,.fad.fa-list-ol:after{content:"\f0cb\f0cb"}.fa-duotone.fa-chart-waterfall:after,.fad.fa-chart-waterfall:after{content:"\e0eb\e0eb"}.fa-duotone.fa-sparkle:after,.fad.fa-sparkle:after{content:"\e5d6\e5d6"}.fa-duotone.fa-face-party:after,.fad.fa-face-party:after{content:"\e383\e383"}.fa-duotone.fa-kidneys:after,.fad.fa-kidneys:after{content:"\f5fb\f5fb"}.fa-duotone.fa-wifi-exclamation:after,.fad.fa-wifi-exclamation:after{content:"\e2cf\e2cf"}.fa-duotone.fa-chart-network:after,.fad.fa-chart-network:after{content:"\f78a\f78a"}.fa-duotone.fa-person-dress-burst:after,.fad.fa-person-dress-burst:after{content:"\e544\e544"}.fa-duotone.fa-dice-d4:after,.fad.fa-dice-d4:after{content:"\f6d0\f6d0"}.fa-duotone.fa-money-check-alt:after,.fa-duotone.fa-money-check-dollar:after,.fad.fa-money-check-alt:after,.fad.fa-money-check-dollar:after{content:"\f53d\f53d"}.fa-duotone.fa-vector-square:after,.fad.fa-vector-square:after{content:"\f5cb\f5cb"}.fa-duotone.fa-bread-slice:after,.fad.fa-bread-slice:after{content:"\f7ec\f7ec"}.fa-duotone.fa-language:after,.fad.fa-language:after{content:"\f1ab\f1ab"}.fa-duotone.fa-wheat-awn-slash:after,.fad.fa-wheat-awn-slash:after{content:"\e338\e338"}.fa-duotone.fa-face-kiss-wink-heart:after,.fa-duotone.fa-kiss-wink-heart:after,.fad.fa-face-kiss-wink-heart:after,.fad.fa-kiss-wink-heart:after{content:"\f598\f598"}.fa-duotone.fa-dagger:after,.fad.fa-dagger:after{content:"\f6cb\f6cb"}.fa-duotone.fa-podium:after,.fad.fa-podium:after{content:"\f680\f680"}.fa-duotone.fa-memo-circle-check:after,.fad.fa-memo-circle-check:after{content:"\e1d9\e1d9"}.fa-duotone.fa-route-highway:after,.fad.fa-route-highway:after{content:"\f61a\f61a"}.fa-duotone.fa-arrow-alt-to-bottom:after,.fa-duotone.fa-down-to-line:after,.fad.fa-arrow-alt-to-bottom:after,.fad.fa-down-to-line:after{content:"\f34a\f34a"}.fa-duotone.fa-filter:after,.fad.fa-filter:after{content:"\f0b0\f0b0"}.fa-duotone.fa-square-g:after,.fad.fa-square-g:after{content:"\e271\e271"}.fa-duotone.fa-circle-phone:after,.fa-duotone.fa-phone-circle:after,.fad.fa-circle-phone:after,.fad.fa-phone-circle:after{content:"\e11b\e11b"}.fa-duotone.fa-clipboard-prescription:after,.fad.fa-clipboard-prescription:after{content:"\f5e8\f5e8"}.fa-duotone.fa-user-nurse-hair:after,.fad.fa-user-nurse-hair:after{content:"\e45d\e45d"}.fa-duotone.fa-question:after,.fad.fa-question:after{content:"\3f\3f"}.fa-duotone.fa-file-signature:after,.fad.fa-file-signature:after{content:"\f573\f573"}.fa-duotone.fa-toggle-large-on:after,.fad.fa-toggle-large-on:after{content:"\e5b1\e5b1"}.fa-duotone.fa-arrows-alt:after,.fa-duotone.fa-up-down-left-right:after,.fad.fa-arrows-alt:after,.fad.fa-up-down-left-right:after{content:"\f0b2\f0b2"}.fa-duotone.fa-dryer-alt:after,.fa-duotone.fa-dryer-heat:after,.fad.fa-dryer-alt:after,.fad.fa-dryer-heat:after{content:"\f862\f862"}.fa-duotone.fa-house-chimney-user:after,.fad.fa-house-chimney-user:after{content:"\e065\e065"}.fa-duotone.fa-hand-holding-heart:after,.fad.fa-hand-holding-heart:after{content:"\f4be\f4be"}.fa-duotone.fa-arrow-up-small-big:after,.fa-duotone.fa-sort-size-up-alt:after,.fad.fa-arrow-up-small-big:after,.fad.fa-sort-size-up-alt:after{content:"\f88f\f88f"}.fa-duotone.fa-train-track:after,.fad.fa-train-track:after{content:"\e453\e453"}.fa-duotone.fa-puzzle-piece:after,.fad.fa-puzzle-piece:after{content:"\f12e\f12e"}.fa-duotone.fa-money-check:after,.fad.fa-money-check:after{content:"\f53c\f53c"}.fa-duotone.fa-star-half-alt:after,.fa-duotone.fa-star-half-stroke:after,.fad.fa-star-half-alt:after,.fad.fa-star-half-stroke:after{content:"\f5c0\f5c0"}.fa-duotone.fa-file-exclamation:after,.fad.fa-file-exclamation:after{content:"\f31a\f31a"}.fa-duotone.fa-code:after,.fad.fa-code:after{content:"\f121\f121"}.fa-duotone.fa-glass-whiskey:after,.fa-duotone.fa-whiskey-glass:after,.fad.fa-glass-whiskey:after,.fad.fa-whiskey-glass:after{content:"\f7a0\f7a0"}.fa-duotone.fa-moon-stars:after,.fad.fa-moon-stars:after{content:"\f755\f755"}.fa-duotone.fa-building-circle-exclamation:after,.fad.fa-building-circle-exclamation:after{content:"\e4d3\e4d3"}.fa-duotone.fa-clothes-hanger:after,.fad.fa-clothes-hanger:after{content:"\e136\e136"}.fa-duotone.fa-mobile-iphone:after,.fa-duotone.fa-mobile-notch:after,.fad.fa-mobile-iphone:after,.fad.fa-mobile-notch:after{content:"\e1ee\e1ee"}.fa-duotone.fa-magnifying-glass-chart:after,.fad.fa-magnifying-glass-chart:after{content:"\e522\e522"}.fa-duotone.fa-arrow-up-right-from-square:after,.fa-duotone.fa-external-link:after,.fad.fa-arrow-up-right-from-square:after,.fad.fa-external-link:after{content:"\f08e\f08e"}.fa-duotone.fa-cubes-stacked:after,.fad.fa-cubes-stacked:after{content:"\e4e6\e4e6"}.fa-duotone.fa-images-user:after,.fad.fa-images-user:after{content:"\e1b9\e1b9"}.fa-duotone.fa-krw:after,.fa-duotone.fa-won-sign:after,.fa-duotone.fa-won:after,.fad.fa-krw:after,.fad.fa-won-sign:after,.fad.fa-won:after{content:"\f159\f159"}.fa-duotone.fa-image-polaroid-user:after,.fad.fa-image-polaroid-user:after{content:"\e1b6\e1b6"}.fa-duotone.fa-virus-covid:after,.fad.fa-virus-covid:after{content:"\e4a8\e4a8"}.fa-duotone.fa-square-ellipsis:after,.fad.fa-square-ellipsis:after{content:"\e26e\e26e"}.fa-duotone.fa-pie:after,.fad.fa-pie:after{content:"\f705\f705"}.fa-duotone.fa-chess-knight-alt:after,.fa-duotone.fa-chess-knight-piece:after,.fad.fa-chess-knight-alt:after,.fad.fa-chess-knight-piece:after{content:"\f442\f442"}.fa-duotone.fa-austral-sign:after,.fad.fa-austral-sign:after{content:"\e0a9\e0a9"}.fa-duotone.fa-cloud-plus:after,.fad.fa-cloud-plus:after{content:"\e35e\e35e"}.fa-duotone.fa-f:after,.fad.fa-f:after{content:"\46\46"}.fa-duotone.fa-leaf:after,.fad.fa-leaf:after{content:"\f06c\f06c"}.fa-duotone.fa-bed-bunk:after,.fad.fa-bed-bunk:after{content:"\f8f8\f8f8"}.fa-duotone.fa-road:after,.fad.fa-road:after{content:"\f018\f018"}.fa-duotone.fa-cab:after,.fa-duotone.fa-taxi:after,.fad.fa-cab:after,.fad.fa-taxi:after{content:"\f1ba\f1ba"}.fa-duotone.fa-person-circle-plus:after,.fad.fa-person-circle-plus:after{content:"\e541\e541"}.fa-duotone.fa-chart-pie:after,.fa-duotone.fa-pie-chart:after,.fad.fa-chart-pie:after,.fad.fa-pie-chart:after{content:"\f200\f200"}.fa-duotone.fa-bolt-lightning:after,.fad.fa-bolt-lightning:after{content:"\e0b7\e0b7"}.fa-duotone.fa-clock-eight:after,.fad.fa-clock-eight:after{content:"\e345\e345"}.fa-duotone.fa-sack-xmark:after,.fad.fa-sack-xmark:after{content:"\e56a\e56a"}.fa-duotone.fa-file-excel:after,.fad.fa-file-excel:after{content:"\f1c3\f1c3"}.fa-duotone.fa-file-contract:after,.fad.fa-file-contract:after{content:"\f56c\f56c"}.fa-duotone.fa-fish-fins:after,.fad.fa-fish-fins:after{content:"\e4f2\e4f2"}.fa-duotone.fa-circle-q:after,.fad.fa-circle-q:after{content:"\e11e\e11e"}.fa-duotone.fa-building-flag:after,.fad.fa-building-flag:after{content:"\e4d5\e4d5"}.fa-duotone.fa-face-grin-beam:after,.fa-duotone.fa-grin-beam:after,.fad.fa-face-grin-beam:after,.fad.fa-grin-beam:after{content:"\f582\f582"}.fa-duotone.fa-object-ungroup:after,.fad.fa-object-ungroup:after{content:"\f248\f248"}.fa-duotone.fa-face-disguise:after,.fad.fa-face-disguise:after{content:"\e370\e370"}.fa-duotone.fa-circle-arrow-down-right:after,.fad.fa-circle-arrow-down-right:after{content:"\e0fa\e0fa"}.fa-duotone.fa-alien-8bit:after,.fa-duotone.fa-alien-monster:after,.fad.fa-alien-8bit:after,.fad.fa-alien-monster:after{content:"\f8f6\f8f6"}.fa-duotone.fa-hand-point-ribbon:after,.fad.fa-hand-point-ribbon:after{content:"\e1a6\e1a6"}.fa-duotone.fa-poop:after,.fad.fa-poop:after{content:"\f619\f619"}.fa-duotone.fa-object-exclude:after,.fad.fa-object-exclude:after{content:"\e49c\e49c"}.fa-duotone.fa-telescope:after,.fad.fa-telescope:after{content:"\e03e\e03e"}.fa-duotone.fa-location-pin:after,.fa-duotone.fa-map-marker:after,.fad.fa-location-pin:after,.fad.fa-map-marker:after{content:"\f041\f041"}.fa-duotone.fa-square-list:after,.fad.fa-square-list:after{content:"\e489\e489"}.fa-duotone.fa-kaaba:after,.fad.fa-kaaba:after{content:"\f66b\f66b"}.fa-duotone.fa-toilet-paper:after,.fad.fa-toilet-paper:after{content:"\f71e\f71e"}.fa-duotone.fa-hard-hat:after,.fa-duotone.fa-hat-hard:after,.fa-duotone.fa-helmet-safety:after,.fad.fa-hard-hat:after,.fad.fa-hat-hard:after,.fad.fa-helmet-safety:after{content:"\f807\f807"}.fa-duotone.fa-comment-code:after,.fad.fa-comment-code:after{content:"\e147\e147"}.fa-duotone.fa-sim-cards:after,.fad.fa-sim-cards:after{content:"\e251\e251"}.fa-duotone.fa-starship:after,.fad.fa-starship:after{content:"\e039\e039"}.fa-duotone.fa-eject:after,.fad.fa-eject:after{content:"\f052\f052"}.fa-duotone.fa-arrow-alt-circle-right:after,.fa-duotone.fa-circle-right:after,.fad.fa-arrow-alt-circle-right:after,.fad.fa-circle-right:after{content:"\f35a\f35a"}.fa-duotone.fa-plane-circle-check:after,.fad.fa-plane-circle-check:after{content:"\e555\e555"}.fa-duotone.fa-seal:after,.fad.fa-seal:after{content:"\e241\e241"}.fa-duotone.fa-user-cowboy:after,.fad.fa-user-cowboy:after{content:"\f8ea\f8ea"}.fa-duotone.fa-hexagon-vertical-nft:after,.fad.fa-hexagon-vertical-nft:after{content:"\e505\e505"}.fa-duotone.fa-face-rolling-eyes:after,.fa-duotone.fa-meh-rolling-eyes:after,.fad.fa-face-rolling-eyes:after,.fad.fa-meh-rolling-eyes:after{content:"\f5a5\f5a5"}.fa-duotone.fa-bread-loaf:after,.fad.fa-bread-loaf:after{content:"\f7eb\f7eb"}.fa-duotone.fa-rings-wedding:after,.fad.fa-rings-wedding:after{content:"\f81b\f81b"}.fa-duotone.fa-object-group:after,.fad.fa-object-group:after{content:"\f247\f247"}.fa-duotone.fa-french-fries:after,.fad.fa-french-fries:after{content:"\f803\f803"}.fa-duotone.fa-chart-line:after,.fa-duotone.fa-line-chart:after,.fad.fa-chart-line:after,.fad.fa-line-chart:after{content:"\f201\f201"}.fa-duotone.fa-calendar-arrow-down:after,.fa-duotone.fa-calendar-download:after,.fad.fa-calendar-arrow-down:after,.fad.fa-calendar-download:after{content:"\e0d0\e0d0"}.fa-duotone.fa-send-back:after,.fad.fa-send-back:after{content:"\f87e\f87e"}.fa-duotone.fa-mask-ventilator:after,.fad.fa-mask-ventilator:after{content:"\e524\e524"}.fa-duotone.fa-signature-lock:after,.fad.fa-signature-lock:after{content:"\e3ca\e3ca"}.fa-duotone.fa-arrow-right:after,.fad.fa-arrow-right:after{content:"\f061\f061"}.fa-duotone.fa-map-signs:after,.fa-duotone.fa-signs-post:after,.fad.fa-map-signs:after,.fad.fa-signs-post:after{content:"\f277\f277"}.fa-duotone.fa-octagon-plus:after,.fa-duotone.fa-plus-octagon:after,.fad.fa-octagon-plus:after,.fad.fa-plus-octagon:after{content:"\f301\f301"}.fa-duotone.fa-cash-register:after,.fad.fa-cash-register:after{content:"\f788\f788"}.fa-duotone.fa-person-circle-question:after,.fad.fa-person-circle-question:after{content:"\e542\e542"}.fa-duotone.fa-melon-slice:after,.fad.fa-melon-slice:after{content:"\e311\e311"}.fa-duotone.fa-space-station-moon:after,.fad.fa-space-station-moon:after{content:"\e033\e033"}.fa-duotone.fa-comment-alt-smile:after,.fa-duotone.fa-message-smile:after,.fad.fa-comment-alt-smile:after,.fad.fa-message-smile:after{content:"\f4aa\f4aa"}.fa-duotone.fa-cup-straw:after,.fad.fa-cup-straw:after{content:"\e363\e363"}.fa-duotone.fa-arrow-alt-from-right:after,.fa-duotone.fa-left-from-line:after,.fad.fa-arrow-alt-from-right:after,.fad.fa-left-from-line:after{content:"\f348\f348"}.fa-duotone.fa-h:after,.fad.fa-h:after{content:"\48\48"}.fa-duotone.fa-basket-shopping-simple:after,.fa-duotone.fa-shopping-basket-alt:after,.fad.fa-basket-shopping-simple:after,.fad.fa-shopping-basket-alt:after{content:"\e0af\e0af"}.fa-duotone.fa-hands-heart:after,.fa-duotone.fa-hands-holding-heart:after,.fad.fa-hands-heart:after,.fad.fa-hands-holding-heart:after{content:"\f4c3\f4c3"}.fa-duotone.fa-clock-nine:after,.fad.fa-clock-nine:after{content:"\e34c\e34c"}.fa-duotone.fa-tarp:after,.fad.fa-tarp:after{content:"\e57b\e57b"}.fa-duotone.fa-face-sleepy:after,.fad.fa-face-sleepy:after{content:"\e38e\e38e"}.fa-duotone.fa-hand-horns:after,.fad.fa-hand-horns:after{content:"\e1a9\e1a9"}.fa-duotone.fa-screwdriver-wrench:after,.fa-duotone.fa-tools:after,.fad.fa-screwdriver-wrench:after,.fad.fa-tools:after{content:"\f7d9\f7d9"}.fa-duotone.fa-arrows-to-eye:after,.fad.fa-arrows-to-eye:after{content:"\e4bf\e4bf"}.fa-duotone.fa-circle-three-quarters:after,.fad.fa-circle-three-quarters:after{content:"\e125\e125"}.fa-duotone.fa-trophy-alt:after,.fa-duotone.fa-trophy-star:after,.fad.fa-trophy-alt:after,.fad.fa-trophy-star:after{content:"\f2eb\f2eb"}.fa-duotone.fa-plug-circle-bolt:after,.fad.fa-plug-circle-bolt:after{content:"\e55b\e55b"}.fa-duotone.fa-face-thermometer:after,.fad.fa-face-thermometer:after{content:"\e39a\e39a"}.fa-duotone.fa-grid-round-4:after,.fad.fa-grid-round-4:after{content:"\e5dd\e5dd"}.fa-duotone.fa-shirt-running:after,.fad.fa-shirt-running:after{content:"\e3c8\e3c8"}.fa-duotone.fa-book-circle-arrow-up:after,.fad.fa-book-circle-arrow-up:after{content:"\e0bd\e0bd"}.fa-duotone.fa-face-nauseated:after,.fad.fa-face-nauseated:after{content:"\e381\e381"}.fa-duotone.fa-heart:after,.fad.fa-heart:after{content:"\f004\f004"}.fa-duotone.fa-file-chart-pie:after,.fad.fa-file-chart-pie:after{content:"\f65a\f65a"}.fa-duotone.fa-mars-and-venus:after,.fad.fa-mars-and-venus:after{content:"\f224\f224"}.fa-duotone.fa-home-user:after,.fa-duotone.fa-house-user:after,.fad.fa-home-user:after,.fad.fa-house-user:after{content:"\e1b0\e1b0"}.fa-duotone.fa-circle-arrow-down-left:after,.fad.fa-circle-arrow-down-left:after{content:"\e0f9\e0f9"}.fa-duotone.fa-dumpster-fire:after,.fad.fa-dumpster-fire:after{content:"\f794\f794"}.fa-duotone.fa-hexagon-minus:after,.fa-duotone.fa-minus-hexagon:after,.fad.fa-hexagon-minus:after,.fad.fa-minus-hexagon:after{content:"\f307\f307"}.fa-duotone.fa-arrow-alt-to-left:after,.fa-duotone.fa-left-to-line:after,.fad.fa-arrow-alt-to-left:after,.fad.fa-left-to-line:after{content:"\f34b\f34b"}.fa-duotone.fa-house-crack:after,.fad.fa-house-crack:after{content:"\e3b1\e3b1"}.fa-duotone.fa-paw-alt:after,.fa-duotone.fa-paw-simple:after,.fad.fa-paw-alt:after,.fad.fa-paw-simple:after{content:"\f701\f701"}.fa-duotone.fa-arrow-left-long-to-line:after,.fad.fa-arrow-left-long-to-line:after{content:"\e3d4\e3d4"}.fa-duotone.fa-brackets-round:after,.fa-duotone.fa-parentheses:after,.fad.fa-brackets-round:after,.fad.fa-parentheses:after{content:"\e0c5\e0c5"}.fa-duotone.fa-cocktail:after,.fa-duotone.fa-martini-glass-citrus:after,.fad.fa-cocktail:after,.fad.fa-martini-glass-citrus:after{content:"\f561\f561"}.fa-duotone.fa-user-shakespeare:after,.fad.fa-user-shakespeare:after{content:"\e2c2\e2c2"}.fa-duotone.fa-arrow-right-to-arc:after,.fad.fa-arrow-right-to-arc:after{content:"\e4b2\e4b2"}.fa-duotone.fa-face-surprise:after,.fa-duotone.fa-surprise:after,.fad.fa-face-surprise:after,.fad.fa-surprise:after{content:"\f5c2\f5c2"}.fa-duotone.fa-bottle-water:after,.fad.fa-bottle-water:after{content:"\e4c5\e4c5"}.fa-duotone.fa-circle-pause:after,.fa-duotone.fa-pause-circle:after,.fad.fa-circle-pause:after,.fad.fa-pause-circle:after{content:"\f28b\f28b"}.fa-duotone.fa-gauge-circle-plus:after,.fad.fa-gauge-circle-plus:after{content:"\e498\e498"}.fa-duotone.fa-folders:after,.fad.fa-folders:after{content:"\f660\f660"}.fa-duotone.fa-angel:after,.fad.fa-angel:after{content:"\f779\f779"}.fa-duotone.fa-value-absolute:after,.fad.fa-value-absolute:after{content:"\f6a6\f6a6"}.fa-duotone.fa-rabbit:after,.fad.fa-rabbit:after{content:"\f708\f708"}.fa-duotone.fa-toilet-paper-slash:after,.fad.fa-toilet-paper-slash:after{content:"\e072\e072"}.fa-duotone.fa-circle-euro:after,.fad.fa-circle-euro:after{content:"\e5ce\e5ce"}.fa-duotone.fa-apple-alt:after,.fa-duotone.fa-apple-whole:after,.fad.fa-apple-alt:after,.fad.fa-apple-whole:after{content:"\f5d1\f5d1"}.fa-duotone.fa-kitchen-set:after,.fad.fa-kitchen-set:after{content:"\e51a\e51a"}.fa-duotone.fa-diamond-half:after,.fad.fa-diamond-half:after{content:"\e5b7\e5b7"}.fa-duotone.fa-lock-alt:after,.fa-duotone.fa-lock-keyhole:after,.fad.fa-lock-alt:after,.fad.fa-lock-keyhole:after{content:"\f30d\f30d"}.fa-duotone.fa-r:after,.fad.fa-r:after{content:"\52\52"}.fa-duotone.fa-temperature-1:after,.fa-duotone.fa-temperature-quarter:after,.fa-duotone.fa-thermometer-1:after,.fa-duotone.fa-thermometer-quarter:after,.fad.fa-temperature-1:after,.fad.fa-temperature-quarter:after,.fad.fa-thermometer-1:after,.fad.fa-thermometer-quarter:after{content:"\f2ca\f2ca"}.fa-duotone.fa-info-square:after,.fa-duotone.fa-square-info:after,.fad.fa-info-square:after,.fad.fa-square-info:after{content:"\f30f\f30f"}.fa-duotone.fa-wifi-slash:after,.fad.fa-wifi-slash:after{content:"\f6ac\f6ac"}.fa-duotone.fa-toilet-paper-xmark:after,.fad.fa-toilet-paper-xmark:after{content:"\e5b3\e5b3"}.fa-duotone.fa-hands-holding-dollar:after,.fa-duotone.fa-hands-usd:after,.fad.fa-hands-holding-dollar:after,.fad.fa-hands-usd:after{content:"\f4c5\f4c5"}.fa-duotone.fa-cube:after,.fad.fa-cube:after{content:"\f1b2\f1b2"}.fa-duotone.fa-arrow-down-triangle-square:after,.fa-duotone.fa-sort-shapes-down:after,.fad.fa-arrow-down-triangle-square:after,.fad.fa-sort-shapes-down:after{content:"\f888\f888"}.fa-duotone.fa-bitcoin-sign:after,.fad.fa-bitcoin-sign:after{content:"\e0b4\e0b4"}.fa-duotone.fa-shutters:after,.fad.fa-shutters:after{content:"\e449\e449"}.fa-duotone.fa-shield-dog:after,.fad.fa-shield-dog:after{content:"\e573\e573"}.fa-duotone.fa-solar-panel:after,.fad.fa-solar-panel:after{content:"\f5ba\f5ba"}.fa-duotone.fa-lock-open:after,.fad.fa-lock-open:after{content:"\f3c1\f3c1"}.fa-duotone.fa-table-tree:after,.fad.fa-table-tree:after{content:"\e293\e293"}.fa-duotone.fa-house-chimney-heart:after,.fad.fa-house-chimney-heart:after{content:"\e1b2\e1b2"}.fa-duotone.fa-tally-3:after,.fad.fa-tally-3:after{content:"\e296\e296"}.fa-duotone.fa-elevator:after,.fad.fa-elevator:after{content:"\e16d\e16d"}.fa-duotone.fa-money-bill-transfer:after,.fad.fa-money-bill-transfer:after{content:"\e528\e528"}.fa-duotone.fa-money-bill-trend-up:after,.fad.fa-money-bill-trend-up:after{content:"\e529\e529"}.fa-duotone.fa-house-flood-water-circle-arrow-right:after,.fad.fa-house-flood-water-circle-arrow-right:after{content:"\e50f\e50f"}.fa-duotone.fa-poll-h:after,.fa-duotone.fa-square-poll-horizontal:after,.fad.fa-poll-h:after,.fad.fa-square-poll-horizontal:after{content:"\f682\f682"}.fa-duotone.fa-circle:after,.fad.fa-circle:after{content:"\f111\f111"}.fa-duotone.fa-cart-circle-exclamation:after,.fad.fa-cart-circle-exclamation:after{content:"\e3f2\e3f2"}.fa-duotone.fa-sword:after,.fad.fa-sword:after{content:"\f71c\f71c"}.fa-duotone.fa-backward-fast:after,.fa-duotone.fa-fast-backward:after,.fad.fa-backward-fast:after,.fad.fa-fast-backward:after{content:"\f049\f049"}.fa-duotone.fa-recycle:after,.fad.fa-recycle:after{content:"\f1b8\f1b8"}.fa-duotone.fa-user-astronaut:after,.fad.fa-user-astronaut:after{content:"\f4fb\f4fb"}.fa-duotone.fa-interrobang:after,.fad.fa-interrobang:after{content:"\e5ba\e5ba"}.fa-duotone.fa-plane-slash:after,.fad.fa-plane-slash:after{content:"\e069\e069"}.fa-duotone.fa-circle-dashed:after,.fad.fa-circle-dashed:after{content:"\e105\e105"}.fa-duotone.fa-trademark:after,.fad.fa-trademark:after{content:"\f25c\f25c"}.fa-duotone.fa-basketball-ball:after,.fa-duotone.fa-basketball:after,.fad.fa-basketball-ball:after,.fad.fa-basketball:after{content:"\f434\f434"}.fa-duotone.fa-fork-knife:after,.fa-duotone.fa-utensils-alt:after,.fad.fa-fork-knife:after,.fad.fa-utensils-alt:after{content:"\f2e6\f2e6"}.fa-duotone.fa-satellite-dish:after,.fad.fa-satellite-dish:after{content:"\f7c0\f7c0"}.fa-duotone.fa-badge-check:after,.fad.fa-badge-check:after{content:"\f336\f336"}.fa-duotone.fa-arrow-alt-circle-up:after,.fa-duotone.fa-circle-up:after,.fad.fa-arrow-alt-circle-up:after,.fad.fa-circle-up:after{content:"\f35b\f35b"}.fa-duotone.fa-slider:after,.fad.fa-slider:after{content:"\e252\e252"}.fa-duotone.fa-mobile-alt:after,.fa-duotone.fa-mobile-screen-button:after,.fad.fa-mobile-alt:after,.fad.fa-mobile-screen-button:after{content:"\f3cd\f3cd"}.fa-duotone.fa-clock-one-thirty:after,.fad.fa-clock-one-thirty:after{content:"\e34f\e34f"}.fa-duotone.fa-inbox-arrow-up:after,.fa-duotone.fa-inbox-out:after,.fad.fa-inbox-arrow-up:after,.fad.fa-inbox-out:after{content:"\f311\f311"}.fa-duotone.fa-cloud-slash:after,.fad.fa-cloud-slash:after{content:"\e137\e137"}.fa-duotone.fa-volume-high:after,.fa-duotone.fa-volume-up:after,.fad.fa-volume-high:after,.fad.fa-volume-up:after{content:"\f028\f028"}.fa-duotone.fa-users-rays:after,.fad.fa-users-rays:after{content:"\e593\e593"}.fa-duotone.fa-wallet:after,.fad.fa-wallet:after{content:"\f555\f555"}.fa-duotone.fa-octagon-check:after,.fad.fa-octagon-check:after{content:"\e426\e426"}.fa-duotone.fa-flatbread-stuffed:after,.fad.fa-flatbread-stuffed:after{content:"\e40c\e40c"}.fa-duotone.fa-clipboard-check:after,.fad.fa-clipboard-check:after{content:"\f46c\f46c"}.fa-duotone.fa-cart-circle-plus:after,.fad.fa-cart-circle-plus:after{content:"\e3f3\e3f3"}.fa-duotone.fa-shipping-timed:after,.fa-duotone.fa-truck-clock:after,.fad.fa-shipping-timed:after,.fad.fa-truck-clock:after{content:"\f48c\f48c"}.fa-duotone.fa-pool-8-ball:after,.fad.fa-pool-8-ball:after{content:"\e3c5\e3c5"}.fa-duotone.fa-file-audio:after,.fad.fa-file-audio:after{content:"\f1c7\f1c7"}.fa-duotone.fa-turn-down-left:after,.fad.fa-turn-down-left:after{content:"\e331\e331"}.fa-duotone.fa-lock-hashtag:after,.fad.fa-lock-hashtag:after{content:"\e423\e423"}.fa-duotone.fa-chart-radar:after,.fad.fa-chart-radar:after{content:"\e0e7\e0e7"}.fa-duotone.fa-staff:after,.fad.fa-staff:after{content:"\f71b\f71b"}.fa-duotone.fa-burger:after,.fa-duotone.fa-hamburger:after,.fad.fa-burger:after,.fad.fa-hamburger:after{content:"\f805\f805"}.fa-duotone.fa-utility-pole:after,.fad.fa-utility-pole:after{content:"\e2c3\e2c3"}.fa-duotone.fa-transporter-6:after,.fad.fa-transporter-6:after{content:"\e2a7\e2a7"}.fa-duotone.fa-wrench:after,.fad.fa-wrench:after{content:"\f0ad\f0ad"}.fa-duotone.fa-bugs:after,.fad.fa-bugs:after{content:"\e4d0\e4d0"}.fa-duotone.fa-vector-polygon:after,.fad.fa-vector-polygon:after{content:"\e2c7\e2c7"}.fa-duotone.fa-diagram-nested:after,.fad.fa-diagram-nested:after{content:"\e157\e157"}.fa-duotone.fa-rupee-sign:after,.fa-duotone.fa-rupee:after,.fad.fa-rupee-sign:after,.fad.fa-rupee:after{content:"\f156\f156"}.fa-duotone.fa-file-image:after,.fad.fa-file-image:after{content:"\f1c5\f1c5"}.fa-duotone.fa-circle-question:after,.fa-duotone.fa-question-circle:after,.fad.fa-circle-question:after,.fad.fa-question-circle:after{content:"\f059\f059"}.fa-duotone.fa-image-user:after,.fad.fa-image-user:after{content:"\e1b8\e1b8"}.fa-duotone.fa-buoy:after,.fad.fa-buoy:after{content:"\e5b5\e5b5"}.fa-duotone.fa-plane-departure:after,.fad.fa-plane-departure:after{content:"\f5b0\f5b0"}.fa-duotone.fa-handshake-slash:after,.fad.fa-handshake-slash:after{content:"\e060\e060"}.fa-duotone.fa-book-bookmark:after,.fad.fa-book-bookmark:after{content:"\e0bb\e0bb"}.fa-duotone.fa-border-center-h:after,.fad.fa-border-center-h:after{content:"\f89c\f89c"}.fa-duotone.fa-can-food:after,.fad.fa-can-food:after{content:"\e3e6\e3e6"}.fa-duotone.fa-typewriter:after,.fad.fa-typewriter:after{content:"\f8e7\f8e7"}.fa-duotone.fa-arrow-right-from-arc:after,.fad.fa-arrow-right-from-arc:after{content:"\e4b1\e4b1"}.fa-duotone.fa-circle-k:after,.fad.fa-circle-k:after{content:"\e113\e113"}.fa-duotone.fa-face-hand-over-mouth:after,.fad.fa-face-hand-over-mouth:after{content:"\e378\e378"}.fa-duotone.fa-popcorn:after,.fad.fa-popcorn:after{content:"\f819\f819"}.fa-duotone.fa-house-flood:after,.fa-duotone.fa-house-water:after,.fad.fa-house-flood:after,.fad.fa-house-water:after{content:"\f74f\f74f"}.fa-duotone.fa-object-subtract:after,.fad.fa-object-subtract:after{content:"\e49e\e49e"}.fa-duotone.fa-code-branch:after,.fad.fa-code-branch:after{content:"\f126\f126"}.fa-duotone.fa-warehouse-alt:after,.fa-duotone.fa-warehouse-full:after,.fad.fa-warehouse-alt:after,.fad.fa-warehouse-full:after{content:"\f495\f495"}.fa-duotone.fa-hat-cowboy:after,.fad.fa-hat-cowboy:after{content:"\f8c0\f8c0"}.fa-duotone.fa-bridge:after,.fad.fa-bridge:after{content:"\e4c8\e4c8"}.fa-duotone.fa-phone-alt:after,.fa-duotone.fa-phone-flip:after,.fad.fa-phone-alt:after,.fad.fa-phone-flip:after{content:"\f879\f879"}.fa-duotone.fa-arrow-down-from-dotted-line:after,.fad.fa-arrow-down-from-dotted-line:after{content:"\e090\e090"}.fa-duotone.fa-file-doc:after,.fad.fa-file-doc:after{content:"\e5ed\e5ed"}.fa-duotone.fa-square-quarters:after,.fad.fa-square-quarters:after{content:"\e44e\e44e"}.fa-duotone.fa-truck-front:after,.fad.fa-truck-front:after{content:"\e2b7\e2b7"}.fa-duotone.fa-cat:after,.fad.fa-cat:after{content:"\f6be\f6be"}.fa-duotone.fa-trash-xmark:after,.fad.fa-trash-xmark:after{content:"\e2b4\e2b4"}.fa-duotone.fa-caret-circle-left:after,.fa-duotone.fa-circle-caret-left:after,.fad.fa-caret-circle-left:after,.fad.fa-circle-caret-left:after{content:"\f32e\f32e"}.fa-duotone.fa-files:after,.fad.fa-files:after{content:"\e178\e178"}.fa-duotone.fa-anchor-circle-exclamation:after,.fad.fa-anchor-circle-exclamation:after{content:"\e4ab\e4ab"}.fa-duotone.fa-face-clouds:after,.fad.fa-face-clouds:after{content:"\e47d\e47d"}.fa-duotone.fa-user-crown:after,.fad.fa-user-crown:after{content:"\f6a4\f6a4"}.fa-duotone.fa-truck-field:after,.fad.fa-truck-field:after{content:"\e58d\e58d"}.fa-duotone.fa-route:after,.fad.fa-route:after{content:"\f4d7\f4d7"}.fa-duotone.fa-cart-circle-check:after,.fad.fa-cart-circle-check:after{content:"\e3f1\e3f1"}.fa-duotone.fa-clipboard-question:after,.fad.fa-clipboard-question:after{content:"\e4e3\e4e3"}.fa-duotone.fa-panorama:after,.fad.fa-panorama:after{content:"\e209\e209"}.fa-duotone.fa-comment-medical:after,.fad.fa-comment-medical:after{content:"\f7f5\f7f5"}.fa-duotone.fa-teeth-open:after,.fad.fa-teeth-open:after{content:"\f62f\f62f"}.fa-duotone.fa-user-tie-hair-long:after,.fad.fa-user-tie-hair-long:after{content:"\e460\e460"}.fa-duotone.fa-file-circle-minus:after,.fad.fa-file-circle-minus:after{content:"\e4ed\e4ed"}.fa-duotone.fa-head-side-medical:after,.fad.fa-head-side-medical:after{content:"\f809\f809"}.fa-duotone.fa-tags:after,.fad.fa-tags:after{content:"\f02c\f02c"}.fa-duotone.fa-wine-glass:after,.fad.fa-wine-glass:after{content:"\f4e3\f4e3"}.fa-duotone.fa-fast-forward:after,.fa-duotone.fa-forward-fast:after,.fad.fa-fast-forward:after,.fad.fa-forward-fast:after{content:"\f050\f050"}.fa-duotone.fa-face-meh-blank:after,.fa-duotone.fa-meh-blank:after,.fad.fa-face-meh-blank:after,.fad.fa-meh-blank:after{content:"\f5a4\f5a4"}.fa-duotone.fa-user-robot:after,.fad.fa-user-robot:after{content:"\e04b\e04b"}.fa-duotone.fa-parking:after,.fa-duotone.fa-square-parking:after,.fad.fa-parking:after,.fad.fa-square-parking:after{content:"\f540\f540"}.fa-duotone.fa-card-diamond:after,.fad.fa-card-diamond:after{content:"\e3ea\e3ea"}.fa-duotone.fa-face-zipper:after,.fad.fa-face-zipper:after{content:"\e3a5\e3a5"}.fa-duotone.fa-face-raised-eyebrow:after,.fad.fa-face-raised-eyebrow:after{content:"\e388\e388"}.fa-duotone.fa-house-signal:after,.fad.fa-house-signal:after{content:"\e012\e012"}.fa-duotone.fa-chevron-square-up:after,.fa-duotone.fa-square-chevron-up:after,.fad.fa-chevron-square-up:after,.fad.fa-square-chevron-up:after{content:"\f32c\f32c"}.fa-duotone.fa-bars-progress:after,.fa-duotone.fa-tasks-alt:after,.fad.fa-bars-progress:after,.fad.fa-tasks-alt:after{content:"\f828\f828"}.fa-duotone.fa-faucet-drip:after,.fad.fa-faucet-drip:after{content:"\e006\e006"}.fa-duotone.fa-arrows-to-line:after,.fad.fa-arrows-to-line:after{content:"\e0a7\e0a7"}.fa-duotone.fa-dolphin:after,.fad.fa-dolphin:after{content:"\e168\e168"}.fa-duotone.fa-arrow-up-right:after,.fad.fa-arrow-up-right:after{content:"\e09f\e09f"}.fa-duotone.fa-circle-r:after,.fad.fa-circle-r:after{content:"\e120\e120"}.fa-duotone.fa-cart-flatbed:after,.fa-duotone.fa-dolly-flatbed:after,.fad.fa-cart-flatbed:after,.fad.fa-dolly-flatbed:after{content:"\f474\f474"}.fa-duotone.fa-ban-smoking:after,.fa-duotone.fa-smoking-ban:after,.fad.fa-ban-smoking:after,.fad.fa-smoking-ban:after{content:"\f54d\f54d"}.fa-duotone.fa-circle-sort-up:after,.fa-duotone.fa-sort-circle-up:after,.fad.fa-circle-sort-up:after,.fad.fa-sort-circle-up:after{content:"\e032\e032"}.fa-duotone.fa-terminal:after,.fad.fa-terminal:after{content:"\f120\f120"}.fa-duotone.fa-mobile-button:after,.fad.fa-mobile-button:after{content:"\f10b\f10b"}.fa-duotone.fa-house-medical-flag:after,.fad.fa-house-medical-flag:after{content:"\e514\e514"}.fa-duotone.fa-basket-shopping:after,.fa-duotone.fa-shopping-basket:after,.fad.fa-basket-shopping:after,.fad.fa-shopping-basket:after{content:"\f291\f291"}.fa-duotone.fa-tape:after,.fad.fa-tape:after{content:"\f4db\f4db"}.fa-duotone.fa-chestnut:after,.fad.fa-chestnut:after{content:"\e3f6\e3f6"}.fa-duotone.fa-bus-alt:after,.fa-duotone.fa-bus-simple:after,.fad.fa-bus-alt:after,.fad.fa-bus-simple:after{content:"\f55e\f55e"}.fa-duotone.fa-eye:after,.fad.fa-eye:after{content:"\f06e\f06e"}.fa-duotone.fa-face-sad-cry:after,.fa-duotone.fa-sad-cry:after,.fad.fa-face-sad-cry:after,.fad.fa-sad-cry:after{content:"\f5b3\f5b3"}.fa-duotone.fa-heat:after,.fad.fa-heat:after{content:"\e00c\e00c"}.fa-duotone.fa-ticket-airline:after,.fad.fa-ticket-airline:after{content:"\e29a\e29a"}.fa-duotone.fa-boot-heeled:after,.fad.fa-boot-heeled:after{content:"\e33f\e33f"}.fa-duotone.fa-arrows-minimize:after,.fa-duotone.fa-compress-arrows:after,.fad.fa-arrows-minimize:after,.fad.fa-compress-arrows:after{content:"\e0a5\e0a5"}.fa-duotone.fa-audio-description:after,.fad.fa-audio-description:after{content:"\f29e\f29e"}.fa-duotone.fa-person-military-to-person:after,.fad.fa-person-military-to-person:after{content:"\e54c\e54c"}.fa-duotone.fa-file-shield:after,.fad.fa-file-shield:after{content:"\e4f0\e4f0"}.fa-duotone.fa-hexagon:after,.fad.fa-hexagon:after{content:"\f312\f312"}.fa-duotone.fa-manhole:after,.fad.fa-manhole:after{content:"\e1d6\e1d6"}.fa-duotone.fa-user-slash:after,.fad.fa-user-slash:after{content:"\f506\f506"}.fa-duotone.fa-pen:after,.fad.fa-pen:after{content:"\f304\f304"}.fa-duotone.fa-tower-observation:after,.fad.fa-tower-observation:after{content:"\e586\e586"}.fa-duotone.fa-floppy-disks:after,.fad.fa-floppy-disks:after{content:"\e183\e183"}.fa-duotone.fa-toilet-paper-blank-under:after,.fa-duotone.fa-toilet-paper-reverse-alt:after,.fad.fa-toilet-paper-blank-under:after,.fad.fa-toilet-paper-reverse-alt:after{content:"\e29f\e29f"}.fa-duotone.fa-file-code:after,.fad.fa-file-code:after{content:"\f1c9\f1c9"}.fa-duotone.fa-signal-5:after,.fa-duotone.fa-signal-perfect:after,.fa-duotone.fa-signal:after,.fad.fa-signal-5:after,.fad.fa-signal-perfect:after,.fad.fa-signal:after{content:"\f012\f012"}.fa-duotone.fa-pump:after,.fad.fa-pump:after{content:"\e442\e442"}.fa-duotone.fa-bus:after,.fad.fa-bus:after{content:"\f207\f207"}.fa-duotone.fa-heart-circle-xmark:after,.fad.fa-heart-circle-xmark:after{content:"\e501\e501"}.fa-duotone.fa-arrow-up-left-from-circle:after,.fad.fa-arrow-up-left-from-circle:after{content:"\e09e\e09e"}.fa-duotone.fa-home-lg:after,.fa-duotone.fa-house-chimney:after,.fad.fa-home-lg:after,.fad.fa-house-chimney:after{content:"\e3af\e3af"}.fa-duotone.fa-window-maximize:after,.fad.fa-window-maximize:after{content:"\f2d0\f2d0"}.fa-duotone.fa-dryer:after,.fad.fa-dryer:after{content:"\f861\f861"}.fa-duotone.fa-face-frown:after,.fa-duotone.fa-frown:after,.fad.fa-face-frown:after,.fad.fa-frown:after{content:"\f119\f119"}.fa-duotone.fa-chess-bishop-alt:after,.fa-duotone.fa-chess-bishop-piece:after,.fad.fa-chess-bishop-alt:after,.fad.fa-chess-bishop-piece:after{content:"\f43b\f43b"}.fa-duotone.fa-shirt-tank-top:after,.fad.fa-shirt-tank-top:after{content:"\e3c9\e3c9"}.fa-duotone.fa-diploma:after,.fa-duotone.fa-scroll-ribbon:after,.fad.fa-diploma:after,.fad.fa-scroll-ribbon:after{content:"\f5ea\f5ea"}.fa-duotone.fa-screencast:after,.fad.fa-screencast:after{content:"\e23e\e23e"}.fa-duotone.fa-walker:after,.fad.fa-walker:after{content:"\f831\f831"}.fa-duotone.fa-prescription:after,.fad.fa-prescription:after{content:"\f5b1\f5b1"}.fa-duotone.fa-shop:after,.fa-duotone.fa-store-alt:after,.fad.fa-shop:after,.fad.fa-store-alt:after{content:"\f54f\f54f"}.fa-duotone.fa-floppy-disk:after,.fa-duotone.fa-save:after,.fad.fa-floppy-disk:after,.fad.fa-save:after{content:"\f0c7\f0c7"}.fa-duotone.fa-vihara:after,.fad.fa-vihara:after{content:"\f6a7\f6a7"}.fa-duotone.fa-face-kiss-closed-eyes:after,.fad.fa-face-kiss-closed-eyes:after{content:"\e37d\e37d"}.fa-duotone.fa-balance-scale-left:after,.fa-duotone.fa-scale-unbalanced:after,.fad.fa-balance-scale-left:after,.fad.fa-scale-unbalanced:after{content:"\f515\f515"}.fa-duotone.fa-file-user:after,.fad.fa-file-user:after{content:"\f65c\f65c"}.fa-duotone.fa-user-police-tie:after,.fad.fa-user-police-tie:after{content:"\e334\e334"}.fa-duotone.fa-face-tongue-money:after,.fad.fa-face-tongue-money:after{content:"\e39d\e39d"}.fa-duotone.fa-tennis-ball:after,.fad.fa-tennis-ball:after{content:"\f45e\f45e"}.fa-duotone.fa-square-l:after,.fad.fa-square-l:after{content:"\e275\e275"}.fa-duotone.fa-sort-asc:after,.fa-duotone.fa-sort-up:after,.fad.fa-sort-asc:after,.fad.fa-sort-up:after{content:"\f0de\f0de"}.fa-duotone.fa-calendar-arrow-up:after,.fa-duotone.fa-calendar-upload:after,.fad.fa-calendar-arrow-up:after,.fad.fa-calendar-upload:after{content:"\e0d1\e0d1"}.fa-duotone.fa-comment-dots:after,.fa-duotone.fa-commenting:after,.fad.fa-comment-dots:after,.fad.fa-commenting:after{content:"\f4ad\f4ad"}.fa-duotone.fa-plant-wilt:after,.fad.fa-plant-wilt:after{content:"\e5aa\e5aa"}.fa-duotone.fa-scarf:after,.fad.fa-scarf:after{content:"\f7c1\f7c1"}.fa-duotone.fa-album-circle-plus:after,.fad.fa-album-circle-plus:after{content:"\e48c\e48c"}.fa-duotone.fa-user-nurse-hair-long:after,.fad.fa-user-nurse-hair-long:after{content:"\e45e\e45e"}.fa-duotone.fa-diamond:after,.fad.fa-diamond:after{content:"\f219\f219"}.fa-duotone.fa-arrow-alt-square-left:after,.fa-duotone.fa-square-left:after,.fad.fa-arrow-alt-square-left:after,.fad.fa-square-left:after{content:"\f351\f351"}.fa-duotone.fa-face-grin-squint:after,.fa-duotone.fa-grin-squint:after,.fad.fa-face-grin-squint:after,.fad.fa-grin-squint:after{content:"\f585\f585"}.fa-duotone.fa-circle-ellipsis-vertical:after,.fad.fa-circle-ellipsis-vertical:after{content:"\e10b\e10b"}.fa-duotone.fa-hand-holding-dollar:after,.fa-duotone.fa-hand-holding-usd:after,.fad.fa-hand-holding-dollar:after,.fad.fa-hand-holding-usd:after{content:"\f4c0\f4c0"}.fa-duotone.fa-grid-dividers:after,.fad.fa-grid-dividers:after{content:"\e3ad\e3ad"}.fa-duotone.fa-bacterium:after,.fad.fa-bacterium:after{content:"\e05a\e05a"}.fa-duotone.fa-hand-pointer:after,.fad.fa-hand-pointer:after{content:"\f25a\f25a"}.fa-duotone.fa-drum-steelpan:after,.fad.fa-drum-steelpan:after{content:"\f56a\f56a"}.fa-duotone.fa-hand-scissors:after,.fad.fa-hand-scissors:after{content:"\f257\f257"}.fa-duotone.fa-hands-praying:after,.fa-duotone.fa-praying-hands:after,.fad.fa-hands-praying:after,.fad.fa-praying-hands:after{content:"\f684\f684"}.fa-duotone.fa-face-pensive:after,.fad.fa-face-pensive:after{content:"\e384\e384"}.fa-duotone.fa-user-music:after,.fad.fa-user-music:after{content:"\f8eb\f8eb"}.fa-duotone.fa-arrow-right-rotate:after,.fa-duotone.fa-arrow-rotate-forward:after,.fa-duotone.fa-arrow-rotate-right:after,.fa-duotone.fa-redo:after,.fad.fa-arrow-right-rotate:after,.fad.fa-arrow-rotate-forward:after,.fad.fa-arrow-rotate-right:after,.fad.fa-redo:after{content:"\f01e\f01e"}.fa-duotone.fa-comments-alt-dollar:after,.fa-duotone.fa-messages-dollar:after,.fad.fa-comments-alt-dollar:after,.fad.fa-messages-dollar:after{content:"\f652\f652"}.fa-duotone.fa-sensor-on:after,.fad.fa-sensor-on:after{content:"\e02b\e02b"}.fa-duotone.fa-balloon:after,.fad.fa-balloon:after{content:"\e2e3\e2e3"}.fa-duotone.fa-biohazard:after,.fad.fa-biohazard:after{content:"\f780\f780"}.fa-duotone.fa-chess-queen-alt:after,.fa-duotone.fa-chess-queen-piece:after,.fad.fa-chess-queen-alt:after,.fad.fa-chess-queen-piece:after{content:"\f446\f446"}.fa-duotone.fa-location-crosshairs:after,.fa-duotone.fa-location:after,.fad.fa-location-crosshairs:after,.fad.fa-location:after{content:"\f601\f601"}.fa-duotone.fa-mars-double:after,.fad.fa-mars-double:after{content:"\f227\f227"}.fa-duotone.fa-house-leave:after,.fa-duotone.fa-house-person-depart:after,.fa-duotone.fa-house-person-leave:after,.fad.fa-house-leave:after,.fad.fa-house-person-depart:after,.fad.fa-house-person-leave:after{content:"\e00f\e00f"}.fa-duotone.fa-ruler-triangle:after,.fad.fa-ruler-triangle:after{content:"\f61c\f61c"}.fa-duotone.fa-card-club:after,.fad.fa-card-club:after{content:"\e3e9\e3e9"}.fa-duotone.fa-child-dress:after,.fad.fa-child-dress:after{content:"\e59c\e59c"}.fa-duotone.fa-users-between-lines:after,.fad.fa-users-between-lines:after{content:"\e591\e591"}.fa-duotone.fa-lungs-virus:after,.fad.fa-lungs-virus:after{content:"\e067\e067"}.fa-duotone.fa-spinner-third:after,.fad.fa-spinner-third:after{content:"\f3f4\f3f4"}.fa-duotone.fa-face-grin-tears:after,.fa-duotone.fa-grin-tears:after,.fad.fa-face-grin-tears:after,.fad.fa-grin-tears:after{content:"\f588\f588"}.fa-duotone.fa-phone:after,.fad.fa-phone:after{content:"\f095\f095"}.fa-duotone.fa-computer-mouse-scrollwheel:after,.fa-duotone.fa-mouse-alt:after,.fad.fa-computer-mouse-scrollwheel:after,.fad.fa-mouse-alt:after{content:"\f8cd\f8cd"}.fa-duotone.fa-calendar-times:after,.fa-duotone.fa-calendar-xmark:after,.fad.fa-calendar-times:after,.fad.fa-calendar-xmark:after{content:"\f273\f273"}.fa-duotone.fa-child-reaching:after,.fad.fa-child-reaching:after{content:"\e59d\e59d"}.fa-duotone.fa-table-layout:after,.fad.fa-table-layout:after{content:"\e290\e290"}.fa-duotone.fa-narwhal:after,.fad.fa-narwhal:after{content:"\f6fe\f6fe"}.fa-duotone.fa-ramp-loading:after,.fad.fa-ramp-loading:after{content:"\f4d4\f4d4"}.fa-duotone.fa-calendar-circle-plus:after,.fad.fa-calendar-circle-plus:after{content:"\e470\e470"}.fa-duotone.fa-toothbrush:after,.fad.fa-toothbrush:after{content:"\f635\f635"}.fa-duotone.fa-border-inner:after,.fad.fa-border-inner:after{content:"\f84e\f84e"}.fa-duotone.fa-paw-claws:after,.fad.fa-paw-claws:after{content:"\f702\f702"}.fa-duotone.fa-kiwi-fruit:after,.fad.fa-kiwi-fruit:after{content:"\e30c\e30c"}.fa-duotone.fa-traffic-light-slow:after,.fad.fa-traffic-light-slow:after{content:"\f639\f639"}.fa-duotone.fa-rectangle-code:after,.fad.fa-rectangle-code:after{content:"\e322\e322"}.fa-duotone.fa-head-side-virus:after,.fad.fa-head-side-virus:after{content:"\e064\e064"}.fa-duotone.fa-keyboard-brightness:after,.fad.fa-keyboard-brightness:after{content:"\e1c0\e1c0"}.fa-duotone.fa-books-medical:after,.fad.fa-books-medical:after{content:"\f7e8\f7e8"}.fa-duotone.fa-lightbulb-slash:after,.fad.fa-lightbulb-slash:after{content:"\f673\f673"}.fa-duotone.fa-home-blank:after,.fa-duotone.fa-house-blank:after,.fad.fa-home-blank:after,.fad.fa-house-blank:after{content:"\e487\e487"}.fa-duotone.fa-square-5:after,.fad.fa-square-5:after{content:"\e25a\e25a"}.fa-duotone.fa-heart-square:after,.fa-duotone.fa-square-heart:after,.fad.fa-heart-square:after,.fad.fa-square-heart:after{content:"\f4c8\f4c8"}.fa-duotone.fa-puzzle:after,.fad.fa-puzzle:after{content:"\e443\e443"}.fa-duotone.fa-user-cog:after,.fa-duotone.fa-user-gear:after,.fad.fa-user-cog:after,.fad.fa-user-gear:after{content:"\f4fe\f4fe"}.fa-duotone.fa-pipe-circle-check:after,.fad.fa-pipe-circle-check:after{content:"\e436\e436"}.fa-duotone.fa-arrow-up-1-9:after,.fa-duotone.fa-sort-numeric-up:after,.fad.fa-arrow-up-1-9:after,.fad.fa-sort-numeric-up:after{content:"\f163\f163"}.fa-duotone.fa-octagon-exclamation:after,.fad.fa-octagon-exclamation:after{content:"\e204\e204"}.fa-duotone.fa-dial-low:after,.fad.fa-dial-low:after{content:"\e15d\e15d"}.fa-duotone.fa-door-closed:after,.fad.fa-door-closed:after{content:"\f52a\f52a"}.fa-duotone.fa-laptop-mobile:after,.fa-duotone.fa-phone-laptop:after,.fad.fa-laptop-mobile:after,.fad.fa-phone-laptop:after{content:"\f87a\f87a"}.fa-duotone.fa-conveyor-belt-alt:after,.fa-duotone.fa-conveyor-belt-boxes:after,.fad.fa-conveyor-belt-alt:after,.fad.fa-conveyor-belt-boxes:after{content:"\f46f\f46f"}.fa-duotone.fa-shield-virus:after,.fad.fa-shield-virus:after{content:"\e06c\e06c"}.fa-duotone.fa-starfighter-alt-advanced:after,.fa-duotone.fa-starfighter-twin-ion-engine-advanced:after,.fad.fa-starfighter-alt-advanced:after,.fad.fa-starfighter-twin-ion-engine-advanced:after{content:"\e28e\e28e"}.fa-duotone.fa-dice-six:after,.fad.fa-dice-six:after{content:"\f526\f526"}.fa-duotone.fa-starfighter-alt:after,.fa-duotone.fa-starfighter-twin-ion-engine:after,.fad.fa-starfighter-alt:after,.fad.fa-starfighter-twin-ion-engine:after{content:"\e038\e038"}.fa-duotone.fa-rocket-launch:after,.fad.fa-rocket-launch:after{content:"\e027\e027"}.fa-duotone.fa-mosquito-net:after,.fad.fa-mosquito-net:after{content:"\e52c\e52c"}.fa-duotone.fa-vent-damper:after,.fad.fa-vent-damper:after{content:"\e465\e465"}.fa-duotone.fa-bridge-water:after,.fad.fa-bridge-water:after{content:"\e4ce\e4ce"}.fa-duotone.fa-ban-bug:after,.fa-duotone.fa-debug:after,.fad.fa-ban-bug:after,.fad.fa-debug:after{content:"\f7f9\f7f9"}.fa-duotone.fa-person-booth:after,.fad.fa-person-booth:after{content:"\f756\f756"}.fa-duotone.fa-text-width:after,.fad.fa-text-width:after{content:"\f035\f035"}.fa-duotone.fa-garage-car:after,.fad.fa-garage-car:after{content:"\e00a\e00a"}.fa-duotone.fa-square-kanban:after,.fad.fa-square-kanban:after{content:"\e488\e488"}.fa-duotone.fa-hat-wizard:after,.fad.fa-hat-wizard:after{content:"\f6e8\f6e8"}.fa-duotone.fa-pen-fancy:after,.fad.fa-pen-fancy:after{content:"\f5ac\f5ac"}.fa-duotone.fa-coffee-pot:after,.fad.fa-coffee-pot:after{content:"\e002\e002"}.fa-duotone.fa-mouse-field:after,.fad.fa-mouse-field:after{content:"\e5a8\e5a8"}.fa-duotone.fa-digging:after,.fa-duotone.fa-person-digging:after,.fad.fa-digging:after,.fad.fa-person-digging:after{content:"\f85e\f85e"}.fa-duotone.fa-shower-alt:after,.fa-duotone.fa-shower-down:after,.fad.fa-shower-alt:after,.fad.fa-shower-down:after{content:"\e24d\e24d"}.fa-duotone.fa-box-circle-check:after,.fad.fa-box-circle-check:after{content:"\e0c4\e0c4"}.fa-duotone.fa-brightness:after,.fad.fa-brightness:after{content:"\e0c9\e0c9"}.fa-duotone.fa-car-side-bolt:after,.fad.fa-car-side-bolt:after{content:"\e344\e344"}.fa-duotone.fa-ornament:after,.fad.fa-ornament:after{content:"\f7b8\f7b8"}.fa-duotone.fa-phone-arrow-down-left:after,.fa-duotone.fa-phone-arrow-down:after,.fa-duotone.fa-phone-incoming:after,.fad.fa-phone-arrow-down-left:after,.fad.fa-phone-arrow-down:after,.fad.fa-phone-incoming:after{content:"\e223\e223"}.fa-duotone.fa-cloud-word:after,.fad.fa-cloud-word:after{content:"\e138\e138"}.fa-duotone.fa-hand-fingers-crossed:after,.fad.fa-hand-fingers-crossed:after{content:"\e1a3\e1a3"}.fa-duotone.fa-trash:after,.fad.fa-trash:after{content:"\f1f8\f1f8"}.fa-duotone.fa-gauge-simple-med:after,.fa-duotone.fa-gauge-simple:after,.fa-duotone.fa-tachometer-average:after,.fad.fa-gauge-simple-med:after,.fad.fa-gauge-simple:after,.fad.fa-tachometer-average:after{content:"\f629\f629"}.fa-duotone.fa-arrow-down-small-big:after,.fa-duotone.fa-sort-size-down-alt:after,.fad.fa-arrow-down-small-big:after,.fad.fa-sort-size-down-alt:after{content:"\f88d\f88d"}.fa-duotone.fa-book-medical:after,.fad.fa-book-medical:after{content:"\f7e6\f7e6"}.fa-duotone.fa-face-melting:after,.fad.fa-face-melting:after{content:"\e483\e483"}.fa-duotone.fa-poo:after,.fad.fa-poo:after{content:"\f2fe\f2fe"}.fa-duotone.fa-pen-alt-slash:after,.fa-duotone.fa-pen-clip-slash:after,.fad.fa-pen-alt-slash:after,.fad.fa-pen-clip-slash:after{content:"\e20f\e20f"}.fa-duotone.fa-quote-right-alt:after,.fa-duotone.fa-quote-right:after,.fad.fa-quote-right-alt:after,.fad.fa-quote-right:after{content:"\f10e\f10e"}.fa-duotone.fa-scroll-old:after,.fad.fa-scroll-old:after{content:"\f70f\f70f"}.fa-duotone.fa-guitars:after,.fad.fa-guitars:after{content:"\f8bf\f8bf"}.fa-duotone.fa-phone-xmark:after,.fad.fa-phone-xmark:after{content:"\e227\e227"}.fa-duotone.fa-hose:after,.fad.fa-hose:after{content:"\e419\e419"}.fa-duotone.fa-clock-six:after,.fad.fa-clock-six:after{content:"\e352\e352"}.fa-duotone.fa-shirt:after,.fa-duotone.fa-t-shirt:after,.fa-duotone.fa-tshirt:after,.fad.fa-shirt:after,.fad.fa-t-shirt:after,.fad.fa-tshirt:after{content:"\f553\f553"}.fa-duotone.fa-billboard:after,.fad.fa-billboard:after{content:"\e5cd\e5cd"}.fa-duotone.fa-square-r:after,.fad.fa-square-r:after{content:"\e27c\e27c"}.fa-duotone.fa-cubes:after,.fad.fa-cubes:after{content:"\f1b3\f1b3"}.fa-duotone.fa-envelope-open-dollar:after,.fad.fa-envelope-open-dollar:after{content:"\f657\f657"}.fa-duotone.fa-divide:after,.fad.fa-divide:after{content:"\f529\f529"}.fa-duotone.fa-sun-cloud:after,.fad.fa-sun-cloud:after{content:"\f763\f763"}.fa-duotone.fa-lamp-floor:after,.fad.fa-lamp-floor:after{content:"\e015\e015"}.fa-duotone.fa-square-7:after,.fad.fa-square-7:after{content:"\e25c\e25c"}.fa-duotone.fa-tenge-sign:after,.fa-duotone.fa-tenge:after,.fad.fa-tenge-sign:after,.fad.fa-tenge:after{content:"\f7d7\f7d7"}.fa-duotone.fa-headphones:after,.fad.fa-headphones:after{content:"\f025\f025"}.fa-duotone.fa-hands-holding:after,.fad.fa-hands-holding:after{content:"\f4c2\f4c2"}.fa-duotone.fa-campfire:after,.fad.fa-campfire:after{content:"\f6ba\f6ba"}.fa-duotone.fa-circle-ampersand:after,.fad.fa-circle-ampersand:after{content:"\e0f8\e0f8"}.fa-duotone.fa-snowflakes:after,.fad.fa-snowflakes:after{content:"\f7cf\f7cf"}.fa-duotone.fa-hands-clapping:after,.fad.fa-hands-clapping:after{content:"\e1a8\e1a8"}.fa-duotone.fa-republican:after,.fad.fa-republican:after{content:"\f75e\f75e"}.fa-duotone.fa-leaf-maple:after,.fad.fa-leaf-maple:after{content:"\f6f6\f6f6"}.fa-duotone.fa-arrow-left:after,.fad.fa-arrow-left:after{content:"\f060\f060"}.fa-duotone.fa-person-circle-xmark:after,.fad.fa-person-circle-xmark:after{content:"\e543\e543"}.fa-duotone.fa-ruler:after,.fad.fa-ruler:after{content:"\f545\f545"}.fa-duotone.fa-cup-straw-swoosh:after,.fad.fa-cup-straw-swoosh:after{content:"\e364\e364"}.fa-duotone.fa-temperature-hot:after,.fa-duotone.fa-temperature-sun:after,.fad.fa-temperature-hot:after,.fad.fa-temperature-sun:after{content:"\f76a\f76a"}.fa-duotone.fa-align-left:after,.fad.fa-align-left:after{content:"\f036\f036"}.fa-duotone.fa-dice-d6:after,.fad.fa-dice-d6:after{content:"\f6d1\f6d1"}.fa-duotone.fa-restroom:after,.fad.fa-restroom:after{content:"\f7bd\f7bd"}.fa-duotone.fa-high-definition:after,.fa-duotone.fa-rectangle-hd:after,.fad.fa-high-definition:after,.fad.fa-rectangle-hd:after{content:"\e1ae\e1ae"}.fa-duotone.fa-j:after,.fad.fa-j:after{content:"\4a\4a"}.fa-duotone.fa-galaxy:after,.fad.fa-galaxy:after{content:"\e008\e008"}.fa-duotone.fa-users-viewfinder:after,.fad.fa-users-viewfinder:after{content:"\e595\e595"}.fa-duotone.fa-file-video:after,.fad.fa-file-video:after{content:"\f1c8\f1c8"}.fa-duotone.fa-cherries:after,.fad.fa-cherries:after{content:"\e0ec\e0ec"}.fa-duotone.fa-external-link-alt:after,.fa-duotone.fa-up-right-from-square:after,.fad.fa-external-link-alt:after,.fad.fa-up-right-from-square:after{content:"\f35d\f35d"}.fa-duotone.fa-circle-sort:after,.fa-duotone.fa-sort-circle:after,.fad.fa-circle-sort:after,.fad.fa-sort-circle:after{content:"\e030\e030"}.fa-duotone.fa-table-cells:after,.fa-duotone.fa-th:after,.fad.fa-table-cells:after,.fad.fa-th:after{content:"\f00a\f00a"}.fa-duotone.fa-file-pdf:after,.fad.fa-file-pdf:after{content:"\f1c1\f1c1"}.fa-duotone.fa-siren:after,.fad.fa-siren:after{content:"\e02d\e02d"}.fa-duotone.fa-arrow-up-to-dotted-line:after,.fad.fa-arrow-up-to-dotted-line:after{content:"\e0a1\e0a1"}.fa-duotone.fa-image-landscape:after,.fa-duotone.fa-landscape:after,.fad.fa-image-landscape:after,.fad.fa-landscape:after{content:"\e1b5\e1b5"}.fa-duotone.fa-tank-water:after,.fad.fa-tank-water:after{content:"\e452\e452"}.fa-duotone.fa-curling-stone:after,.fa-duotone.fa-curling:after,.fad.fa-curling-stone:after,.fad.fa-curling:after{content:"\f44a\f44a"}.fa-duotone.fa-gamepad-alt:after,.fa-duotone.fa-gamepad-modern:after,.fad.fa-gamepad-alt:after,.fad.fa-gamepad-modern:after{content:"\e5a2\e5a2"}.fa-duotone.fa-messages-question:after,.fad.fa-messages-question:after{content:"\e1e7\e1e7"}.fa-duotone.fa-bible:after,.fa-duotone.fa-book-bible:after,.fad.fa-bible:after,.fad.fa-book-bible:after{content:"\f647\f647"}.fa-duotone.fa-o:after,.fad.fa-o:after{content:"\4f\4f"}.fa-duotone.fa-medkit:after,.fa-duotone.fa-suitcase-medical:after,.fad.fa-medkit:after,.fad.fa-suitcase-medical:after{content:"\f0fa\f0fa"}.fa-duotone.fa-briefcase-arrow-right:after,.fad.fa-briefcase-arrow-right:after{content:"\e2f2\e2f2"}.fa-duotone.fa-expand-wide:after,.fad.fa-expand-wide:after{content:"\f320\f320"}.fa-duotone.fa-clock-eleven-thirty:after,.fad.fa-clock-eleven-thirty:after{content:"\e348\e348"}.fa-duotone.fa-rv:after,.fad.fa-rv:after{content:"\f7be\f7be"}.fa-duotone.fa-user-secret:after,.fad.fa-user-secret:after{content:"\f21b\f21b"}.fa-duotone.fa-otter:after,.fad.fa-otter:after{content:"\f700\f700"}.fa-duotone.fa-dreidel:after,.fad.fa-dreidel:after{content:"\f792\f792"}.fa-duotone.fa-female:after,.fa-duotone.fa-person-dress:after,.fad.fa-female:after,.fad.fa-person-dress:after{content:"\f182\f182"}.fa-duotone.fa-comment-dollar:after,.fad.fa-comment-dollar:after{content:"\f651\f651"}.fa-duotone.fa-briefcase-clock:after,.fa-duotone.fa-business-time:after,.fad.fa-briefcase-clock:after,.fad.fa-business-time:after{content:"\f64a\f64a"}.fa-duotone.fa-flower-tulip:after,.fad.fa-flower-tulip:after{content:"\f801\f801"}.fa-duotone.fa-people-pants-simple:after,.fad.fa-people-pants-simple:after{content:"\e21a\e21a"}.fa-duotone.fa-cloud-drizzle:after,.fad.fa-cloud-drizzle:after{content:"\f738\f738"}.fa-duotone.fa-table-cells-large:after,.fa-duotone.fa-th-large:after,.fad.fa-table-cells-large:after,.fad.fa-th-large:after{content:"\f009\f009"}.fa-duotone.fa-book-tanakh:after,.fa-duotone.fa-tanakh:after,.fad.fa-book-tanakh:after,.fad.fa-tanakh:after{content:"\f827\f827"}.fa-duotone.fa-solar-system:after,.fad.fa-solar-system:after{content:"\e02f\e02f"}.fa-duotone.fa-seal-question:after,.fad.fa-seal-question:after{content:"\e243\e243"}.fa-duotone.fa-phone-volume:after,.fa-duotone.fa-volume-control-phone:after,.fad.fa-phone-volume:after,.fad.fa-volume-control-phone:after{content:"\f2a0\f2a0"}.fa-duotone.fa-disc-drive:after,.fad.fa-disc-drive:after{content:"\f8b5\f8b5"}.fa-duotone.fa-hat-cowboy-side:after,.fad.fa-hat-cowboy-side:after{content:"\f8c1\f8c1"}.fa-duotone.fa-rows:after,.fa-duotone.fa-table-rows:after,.fad.fa-rows:after,.fad.fa-table-rows:after{content:"\e292\e292"}.fa-duotone.fa-location-exclamation:after,.fa-duotone.fa-map-marker-exclamation:after,.fad.fa-location-exclamation:after,.fad.fa-map-marker-exclamation:after{content:"\f608\f608"}.fa-duotone.fa-face-fearful:after,.fad.fa-face-fearful:after{content:"\e375\e375"}.fa-duotone.fa-clipboard-user:after,.fad.fa-clipboard-user:after{content:"\f7f3\f7f3"}.fa-duotone.fa-bus-school:after,.fad.fa-bus-school:after{content:"\f5dd\f5dd"}.fa-duotone.fa-film-slash:after,.fad.fa-film-slash:after{content:"\e179\e179"}.fa-duotone.fa-square-arrow-down-right:after,.fad.fa-square-arrow-down-right:after{content:"\e262\e262"}.fa-duotone.fa-book-sparkles:after,.fa-duotone.fa-book-spells:after,.fad.fa-book-sparkles:after,.fad.fa-book-spells:after{content:"\f6b8\f6b8"}.fa-duotone.fa-washer:after,.fa-duotone.fa-washing-machine:after,.fad.fa-washer:after,.fad.fa-washing-machine:after{content:"\f898\f898"}.fa-duotone.fa-child:after,.fad.fa-child:after{content:"\f1ae\f1ae"}.fa-duotone.fa-lira-sign:after,.fad.fa-lira-sign:after{content:"\f195\f195"}.fa-duotone.fa-user-visor:after,.fad.fa-user-visor:after{content:"\e04c\e04c"}.fa-duotone.fa-file-plus-minus:after,.fad.fa-file-plus-minus:after{content:"\e177\e177"}.fa-duotone.fa-chess-clock-alt:after,.fa-duotone.fa-chess-clock-flip:after,.fad.fa-chess-clock-alt:after,.fad.fa-chess-clock-flip:after{content:"\f43e\f43e"}.fa-duotone.fa-satellite:after,.fad.fa-satellite:after{content:"\f7bf\f7bf"}.fa-duotone.fa-plane-lock:after,.fad.fa-plane-lock:after{content:"\e558\e558"}.fa-duotone.fa-steering-wheel:after,.fad.fa-steering-wheel:after{content:"\f622\f622"}.fa-duotone.fa-tag:after,.fad.fa-tag:after{content:"\f02b\f02b"}.fa-duotone.fa-stretcher:after,.fad.fa-stretcher:after{content:"\f825\f825"}.fa-duotone.fa-book-law:after,.fa-duotone.fa-book-section:after,.fad.fa-book-law:after,.fad.fa-book-section:after{content:"\e0c1\e0c1"}.fa-duotone.fa-inboxes:after,.fad.fa-inboxes:after{content:"\e1bb\e1bb"}.fa-duotone.fa-coffee-bean:after,.fad.fa-coffee-bean:after{content:"\e13e\e13e"}.fa-duotone.fa-circle-yen:after,.fad.fa-circle-yen:after{content:"\e5d0\e5d0"}.fa-duotone.fa-brackets-curly:after,.fad.fa-brackets-curly:after{content:"\f7ea\f7ea"}.fa-duotone.fa-ellipsis-stroke-vertical:after,.fa-duotone.fa-ellipsis-v-alt:after,.fad.fa-ellipsis-stroke-vertical:after,.fad.fa-ellipsis-v-alt:after{content:"\f39c\f39c"}.fa-duotone.fa-comment:after,.fad.fa-comment:after{content:"\f075\f075"}.fa-duotone.fa-square-1:after,.fad.fa-square-1:after{content:"\e256\e256"}.fa-duotone.fa-birthday-cake:after,.fa-duotone.fa-cake-candles:after,.fa-duotone.fa-cake:after,.fad.fa-birthday-cake:after,.fad.fa-cake-candles:after,.fad.fa-cake:after{content:"\f1fd\f1fd"}.fa-duotone.fa-head-side:after,.fad.fa-head-side:after{content:"\f6e9\f6e9"}.fa-duotone.fa-envelope:after,.fad.fa-envelope:after{content:"\f0e0\f0e0"}.fa-duotone.fa-dolly-empty:after,.fad.fa-dolly-empty:after{content:"\f473\f473"}.fa-duotone.fa-face-tissue:after,.fad.fa-face-tissue:after{content:"\e39c\e39c"}.fa-duotone.fa-angle-double-up:after,.fa-duotone.fa-angles-up:after,.fad.fa-angle-double-up:after,.fad.fa-angles-up:after{content:"\f102\f102"}.fa-duotone.fa-bin-recycle:after,.fad.fa-bin-recycle:after{content:"\e5f7\e5f7"}.fa-duotone.fa-paperclip:after,.fad.fa-paperclip:after{content:"\f0c6\f0c6"}.fa-duotone.fa-chart-line-down:after,.fad.fa-chart-line-down:after{content:"\f64d\f64d"}.fa-duotone.fa-arrow-right-to-city:after,.fad.fa-arrow-right-to-city:after{content:"\e4b3\e4b3"}.fa-duotone.fa-lock-a:after,.fad.fa-lock-a:after{content:"\e422\e422"}.fa-duotone.fa-ribbon:after,.fad.fa-ribbon:after{content:"\f4d6\f4d6"}.fa-duotone.fa-lungs:after,.fad.fa-lungs:after{content:"\f604\f604"}.fa-duotone.fa-person-pinball:after,.fad.fa-person-pinball:after{content:"\e21d\e21d"}.fa-duotone.fa-arrow-up-9-1:after,.fa-duotone.fa-sort-numeric-up-alt:after,.fad.fa-arrow-up-9-1:after,.fad.fa-sort-numeric-up-alt:after{content:"\f887\f887"}.fa-duotone.fa-apple-core:after,.fad.fa-apple-core:after{content:"\e08f\e08f"}.fa-duotone.fa-circle-y:after,.fad.fa-circle-y:after{content:"\e12f\e12f"}.fa-duotone.fa-h6:after,.fad.fa-h6:after{content:"\e413\e413"}.fa-duotone.fa-litecoin-sign:after,.fad.fa-litecoin-sign:after{content:"\e1d3\e1d3"}.fa-duotone.fa-circle-small:after,.fad.fa-circle-small:after{content:"\e122\e122"}.fa-duotone.fa-border-none:after,.fad.fa-border-none:after{content:"\f850\f850"}.fa-duotone.fa-arrow-turn-down-left:after,.fad.fa-arrow-turn-down-left:after{content:"\e2e1\e2e1"}.fa-duotone.fa-circle-nodes:after,.fad.fa-circle-nodes:after{content:"\e4e2\e4e2"}.fa-duotone.fa-parachute-box:after,.fad.fa-parachute-box:after{content:"\f4cd\f4cd"}.fa-duotone.fa-comment-alt-medical:after,.fa-duotone.fa-message-medical:after,.fad.fa-comment-alt-medical:after,.fad.fa-message-medical:after{content:"\f7f4\f7f4"}.fa-duotone.fa-rugby-ball:after,.fad.fa-rugby-ball:after{content:"\e3c6\e3c6"}.fa-duotone.fa-comment-music:after,.fad.fa-comment-music:after{content:"\f8b0\f8b0"}.fa-duotone.fa-indent:after,.fad.fa-indent:after{content:"\f03c\f03c"}.fa-duotone.fa-tree-alt:after,.fa-duotone.fa-tree-deciduous:after,.fad.fa-tree-alt:after,.fad.fa-tree-deciduous:after{content:"\f400\f400"}.fa-duotone.fa-puzzle-piece-alt:after,.fa-duotone.fa-puzzle-piece-simple:after,.fad.fa-puzzle-piece-alt:after,.fad.fa-puzzle-piece-simple:after{content:"\e231\e231"}.fa-duotone.fa-truck-field-un:after,.fad.fa-truck-field-un:after{content:"\e58e\e58e"}.fa-duotone.fa-nfc-trash:after,.fad.fa-nfc-trash:after{content:"\e1fd\e1fd"}.fa-duotone.fa-hourglass-empty:after,.fa-duotone.fa-hourglass:after,.fad.fa-hourglass-empty:after,.fad.fa-hourglass:after{content:"\f254\f254"}.fa-duotone.fa-mountain:after,.fad.fa-mountain:after{content:"\f6fc\f6fc"}.fa-duotone.fa-file-times:after,.fa-duotone.fa-file-xmark:after,.fad.fa-file-times:after,.fad.fa-file-xmark:after{content:"\f317\f317"}.fa-duotone.fa-home-heart:after,.fa-duotone.fa-house-heart:after,.fad.fa-home-heart:after,.fad.fa-house-heart:after{content:"\f4c9\f4c9"}.fa-duotone.fa-house-chimney-blank:after,.fad.fa-house-chimney-blank:after{content:"\e3b0\e3b0"}.fa-duotone.fa-meter-bolt:after,.fad.fa-meter-bolt:after{content:"\e1e9\e1e9"}.fa-duotone.fa-user-doctor:after,.fa-duotone.fa-user-md:after,.fad.fa-user-doctor:after,.fad.fa-user-md:after{content:"\f0f0\f0f0"}.fa-duotone.fa-slash-back:after,.fad.fa-slash-back:after{content:"\5c\5c"}.fa-duotone.fa-circle-info:after,.fa-duotone.fa-info-circle:after,.fad.fa-circle-info:after,.fad.fa-info-circle:after{content:"\f05a\f05a"}.fa-duotone.fa-fishing-rod:after,.fad.fa-fishing-rod:after{content:"\e3a8\e3a8"}.fa-duotone.fa-hammer-crash:after,.fad.fa-hammer-crash:after{content:"\e414\e414"}.fa-duotone.fa-message-heart:after,.fad.fa-message-heart:after{content:"\e5c9\e5c9"}.fa-duotone.fa-cloud-meatball:after,.fad.fa-cloud-meatball:after{content:"\f73b\f73b"}.fa-duotone.fa-camera-polaroid:after,.fad.fa-camera-polaroid:after{content:"\f8aa\f8aa"}.fa-duotone.fa-camera-alt:after,.fa-duotone.fa-camera:after,.fad.fa-camera-alt:after,.fad.fa-camera:after{content:"\f030\f030"}.fa-duotone.fa-square-virus:after,.fad.fa-square-virus:after{content:"\e578\e578"}.fa-duotone.fa-cart-arrow-up:after,.fad.fa-cart-arrow-up:after{content:"\e3ee\e3ee"}.fa-duotone.fa-meteor:after,.fad.fa-meteor:after{content:"\f753\f753"}.fa-duotone.fa-car-on:after,.fad.fa-car-on:after{content:"\e4dd\e4dd"}.fa-duotone.fa-sleigh:after,.fad.fa-sleigh:after{content:"\f7cc\f7cc"}.fa-duotone.fa-arrow-down-1-9:after,.fa-duotone.fa-sort-numeric-asc:after,.fa-duotone.fa-sort-numeric-down:after,.fad.fa-arrow-down-1-9:after,.fad.fa-sort-numeric-asc:after,.fad.fa-sort-numeric-down:after{content:"\f162\f162"}.fa-duotone.fa-buoy-mooring:after,.fad.fa-buoy-mooring:after{content:"\e5b6\e5b6"}.fa-duotone.fa-square-4:after,.fad.fa-square-4:after{content:"\e259\e259"}.fa-duotone.fa-hand-holding-droplet:after,.fa-duotone.fa-hand-holding-water:after,.fad.fa-hand-holding-droplet:after,.fad.fa-hand-holding-water:after{content:"\f4c1\f4c1"}.fa-duotone.fa-tricycle-adult:after,.fad.fa-tricycle-adult:after{content:"\e5c4\e5c4"}.fa-duotone.fa-waveform:after,.fad.fa-waveform:after{content:"\f8f1\f8f1"}.fa-duotone.fa-water:after,.fad.fa-water:after{content:"\f773\f773"}.fa-duotone.fa-star-sharp-half-alt:after,.fa-duotone.fa-star-sharp-half-stroke:after,.fad.fa-star-sharp-half-alt:after,.fad.fa-star-sharp-half-stroke:after{content:"\e28d\e28d"}.fa-duotone.fa-nfc-signal:after,.fad.fa-nfc-signal:after{content:"\e1fb\e1fb"}.fa-duotone.fa-plane-prop:after,.fad.fa-plane-prop:after{content:"\e22b\e22b"}.fa-duotone.fa-calendar-check:after,.fad.fa-calendar-check:after{content:"\f274\f274"}.fa-duotone.fa-clock-desk:after,.fad.fa-clock-desk:after{content:"\e134\e134"}.fa-duotone.fa-calendar-clock:after,.fa-duotone.fa-calendar-time:after,.fad.fa-calendar-clock:after,.fad.fa-calendar-time:after{content:"\e0d2\e0d2"}.fa-duotone.fa-braille:after,.fad.fa-braille:after{content:"\f2a1\f2a1"}.fa-duotone.fa-prescription-bottle-alt:after,.fa-duotone.fa-prescription-bottle-medical:after,.fad.fa-prescription-bottle-alt:after,.fad.fa-prescription-bottle-medical:after{content:"\f486\f486"}.fa-duotone.fa-plate-utensils:after,.fad.fa-plate-utensils:after{content:"\e43b\e43b"}.fa-duotone.fa-family-pants:after,.fad.fa-family-pants:after{content:"\e302\e302"}.fa-duotone.fa-hose-reel:after,.fad.fa-hose-reel:after{content:"\e41a\e41a"}.fa-duotone.fa-house-window:after,.fad.fa-house-window:after{content:"\e3b3\e3b3"}.fa-duotone.fa-landmark:after,.fad.fa-landmark:after{content:"\f66f\f66f"}.fa-duotone.fa-truck:after,.fad.fa-truck:after{content:"\f0d1\f0d1"}.fa-duotone.fa-crosshairs:after,.fad.fa-crosshairs:after{content:"\f05b\f05b"}.fa-duotone.fa-cloud-rainbow:after,.fad.fa-cloud-rainbow:after{content:"\f73e\f73e"}.fa-duotone.fa-person-cane:after,.fad.fa-person-cane:after{content:"\e53c\e53c"}.fa-duotone.fa-alien:after,.fad.fa-alien:after{content:"\f8f5\f8f5"}.fa-duotone.fa-tent:after,.fad.fa-tent:after{content:"\e57d\e57d"}.fa-duotone.fa-laptop-binary:after,.fad.fa-laptop-binary:after{content:"\e5e7\e5e7"}.fa-duotone.fa-vest-patches:after,.fad.fa-vest-patches:after{content:"\e086\e086"}.fa-duotone.fa-people-dress-simple:after,.fad.fa-people-dress-simple:after{content:"\e218\e218"}.fa-duotone.fa-check-double:after,.fad.fa-check-double:after{content:"\f560\f560"}.fa-duotone.fa-arrow-down-a-z:after,.fa-duotone.fa-sort-alpha-asc:after,.fa-duotone.fa-sort-alpha-down:after,.fad.fa-arrow-down-a-z:after,.fad.fa-sort-alpha-asc:after,.fad.fa-sort-alpha-down:after{content:"\f15d\f15d"}.fa-duotone.fa-bowling-ball-pin:after,.fad.fa-bowling-ball-pin:after{content:"\e0c3\e0c3"}.fa-duotone.fa-bell-school-slash:after,.fad.fa-bell-school-slash:after{content:"\f5d6\f5d6"}.fa-duotone.fa-plus-large:after,.fad.fa-plus-large:after{content:"\e59e\e59e"}.fa-duotone.fa-money-bill-wheat:after,.fad.fa-money-bill-wheat:after{content:"\e52a\e52a"}.fa-duotone.fa-camera-viewfinder:after,.fa-duotone.fa-screenshot:after,.fad.fa-camera-viewfinder:after,.fad.fa-screenshot:after{content:"\e0da\e0da"}.fa-duotone.fa-comment-alt-music:after,.fa-duotone.fa-message-music:after,.fad.fa-comment-alt-music:after,.fad.fa-message-music:after{content:"\f8af\f8af"}.fa-duotone.fa-car-building:after,.fad.fa-car-building:after{content:"\f859\f859"}.fa-duotone.fa-border-bottom-right:after,.fa-duotone.fa-border-style-alt:after,.fad.fa-border-bottom-right:after,.fad.fa-border-style-alt:after{content:"\f854\f854"}.fa-duotone.fa-octagon:after,.fad.fa-octagon:after{content:"\f306\f306"}.fa-duotone.fa-comment-arrow-up-right:after,.fad.fa-comment-arrow-up-right:after{content:"\e145\e145"}.fa-duotone.fa-octagon-divide:after,.fad.fa-octagon-divide:after{content:"\e203\e203"}.fa-duotone.fa-cookie:after,.fad.fa-cookie:after{content:"\f563\f563"}.fa-duotone.fa-arrow-left-rotate:after,.fa-duotone.fa-arrow-rotate-back:after,.fa-duotone.fa-arrow-rotate-backward:after,.fa-duotone.fa-arrow-rotate-left:after,.fa-duotone.fa-undo:after,.fad.fa-arrow-left-rotate:after,.fad.fa-arrow-rotate-back:after,.fad.fa-arrow-rotate-backward:after,.fad.fa-arrow-rotate-left:after,.fad.fa-undo:after{content:"\f0e2\f0e2"}.fa-duotone.fa-tv-music:after,.fad.fa-tv-music:after{content:"\f8e6\f8e6"}.fa-duotone.fa-hard-drive:after,.fa-duotone.fa-hdd:after,.fad.fa-hard-drive:after,.fad.fa-hdd:after{content:"\f0a0\f0a0"}.fa-duotone.fa-reel:after,.fad.fa-reel:after{content:"\e238\e238"}.fa-duotone.fa-face-grin-squint-tears:after,.fa-duotone.fa-grin-squint-tears:after,.fad.fa-face-grin-squint-tears:after,.fad.fa-grin-squint-tears:after{content:"\f586\f586"}.fa-duotone.fa-dumbbell:after,.fad.fa-dumbbell:after{content:"\f44b\f44b"}.fa-duotone.fa-list-alt:after,.fa-duotone.fa-rectangle-list:after,.fad.fa-list-alt:after,.fad.fa-rectangle-list:after{content:"\f022\f022"}.fa-duotone.fa-tarp-droplet:after,.fad.fa-tarp-droplet:after{content:"\e57c\e57c"}.fa-duotone.fa-alarm-exclamation:after,.fad.fa-alarm-exclamation:after{content:"\f843\f843"}.fa-duotone.fa-house-medical-circle-check:after,.fad.fa-house-medical-circle-check:after{content:"\e511\e511"}.fa-duotone.fa-traffic-cone:after,.fad.fa-traffic-cone:after{content:"\f636\f636"}.fa-duotone.fa-grate:after,.fad.fa-grate:after{content:"\e193\e193"}.fa-duotone.fa-arrow-down-right:after,.fad.fa-arrow-down-right:after{content:"\e093\e093"}.fa-duotone.fa-person-skiing-nordic:after,.fa-duotone.fa-skiing-nordic:after,.fad.fa-person-skiing-nordic:after,.fad.fa-skiing-nordic:after{content:"\f7ca\f7ca"}.fa-duotone.fa-calendar-plus:after,.fad.fa-calendar-plus:after{content:"\f271\f271"}.fa-duotone.fa-person-from-portal:after,.fa-duotone.fa-portal-exit:after,.fad.fa-person-from-portal:after,.fad.fa-portal-exit:after{content:"\e023\e023"}.fa-duotone.fa-plane-arrival:after,.fad.fa-plane-arrival:after{content:"\f5af\f5af"}.fa-duotone.fa-cowbell-circle-plus:after,.fa-duotone.fa-cowbell-more:after,.fad.fa-cowbell-circle-plus:after,.fad.fa-cowbell-more:after{content:"\f8b4\f8b4"}.fa-duotone.fa-arrow-alt-circle-left:after,.fa-duotone.fa-circle-left:after,.fad.fa-arrow-alt-circle-left:after,.fad.fa-circle-left:after{content:"\f359\f359"}.fa-duotone.fa-distribute-spacing-vertical:after,.fad.fa-distribute-spacing-vertical:after{content:"\e366\e366"}.fa-duotone.fa-signal-alt-2:after,.fa-duotone.fa-signal-bars-fair:after,.fad.fa-signal-alt-2:after,.fad.fa-signal-bars-fair:after{content:"\f692\f692"}.fa-duotone.fa-sportsball:after,.fad.fa-sportsball:after{content:"\e44b\e44b"}.fa-duotone.fa-game-console-handheld-crank:after,.fad.fa-game-console-handheld-crank:after{content:"\e5b9\e5b9"}.fa-duotone.fa-subway:after,.fa-duotone.fa-train-subway:after,.fad.fa-subway:after,.fad.fa-train-subway:after{content:"\f239\f239"}.fa-duotone.fa-chart-gantt:after,.fad.fa-chart-gantt:after{content:"\e0e4\e0e4"}.fa-duotone.fa-face-smile-upside-down:after,.fad.fa-face-smile-upside-down:after{content:"\e395\e395"}.fa-duotone.fa-ball-pile:after,.fad.fa-ball-pile:after{content:"\f77e\f77e"}.fa-duotone.fa-badge-dollar:after,.fad.fa-badge-dollar:after{content:"\f645\f645"}.fa-duotone.fa-money-bills-alt:after,.fa-duotone.fa-money-bills-simple:after,.fad.fa-money-bills-alt:after,.fad.fa-money-bills-simple:after{content:"\e1f4\e1f4"}.fa-duotone.fa-list-timeline:after,.fad.fa-list-timeline:after{content:"\e1d1\e1d1"}.fa-duotone.fa-indian-rupee-sign:after,.fa-duotone.fa-indian-rupee:after,.fa-duotone.fa-inr:after,.fad.fa-indian-rupee-sign:after,.fad.fa-indian-rupee:after,.fad.fa-inr:after{content:"\e1bc\e1bc"}.fa-duotone.fa-crop-alt:after,.fa-duotone.fa-crop-simple:after,.fad.fa-crop-alt:after,.fad.fa-crop-simple:after{content:"\f565\f565"}.fa-duotone.fa-money-bill-1:after,.fa-duotone.fa-money-bill-alt:after,.fad.fa-money-bill-1:after,.fad.fa-money-bill-alt:after{content:"\f3d1\f3d1"}.fa-duotone.fa-left-long:after,.fa-duotone.fa-long-arrow-alt-left:after,.fad.fa-left-long:after,.fad.fa-long-arrow-alt-left:after{content:"\f30a\f30a"}.fa-duotone.fa-keyboard-down:after,.fad.fa-keyboard-down:after{content:"\e1c2\e1c2"}.fa-duotone.fa-circle-up-right:after,.fad.fa-circle-up-right:after{content:"\e129\e129"}.fa-duotone.fa-cloud-bolt-moon:after,.fa-duotone.fa-thunderstorm-moon:after,.fad.fa-cloud-bolt-moon:after,.fad.fa-thunderstorm-moon:after{content:"\f76d\f76d"}.fa-duotone.fa-dna:after,.fad.fa-dna:after{content:"\f471\f471"}.fa-duotone.fa-virus-slash:after,.fad.fa-virus-slash:after{content:"\e075\e075"}.fa-duotone.fa-bracket-round-right:after,.fad.fa-bracket-round-right:after{content:"\29\29"}.fa-duotone.fa-circle-sterling:after,.fad.fa-circle-sterling:after{content:"\e5cf\e5cf"}.fa-duotone.fa-circle-5:after,.fad.fa-circle-5:after{content:"\e0f2\e0f2"}.fa-duotone.fa-minus:after,.fa-duotone.fa-subtract:after,.fad.fa-minus:after,.fad.fa-subtract:after{content:"\f068\f068"}.fa-duotone.fa-fire-flame:after,.fa-duotone.fa-flame:after,.fad.fa-fire-flame:after,.fad.fa-flame:after{content:"\f6df\f6df"}.fa-duotone.fa-arrow-alt-to-right:after,.fa-duotone.fa-right-to-line:after,.fad.fa-arrow-alt-to-right:after,.fad.fa-right-to-line:after{content:"\f34c\f34c"}.fa-duotone.fa-gif:after,.fad.fa-gif:after{content:"\e190\e190"}.fa-duotone.fa-chess:after,.fad.fa-chess:after{content:"\f439\f439"}.fa-duotone.fa-trash-slash:after,.fad.fa-trash-slash:after{content:"\e2b3\e2b3"}.fa-duotone.fa-arrow-left-long:after,.fa-duotone.fa-long-arrow-left:after,.fad.fa-arrow-left-long:after,.fad.fa-long-arrow-left:after{content:"\f177\f177"}.fa-duotone.fa-plug-circle-check:after,.fad.fa-plug-circle-check:after{content:"\e55c\e55c"}.fa-duotone.fa-font-case:after,.fad.fa-font-case:after{content:"\f866\f866"}.fa-duotone.fa-street-view:after,.fad.fa-street-view:after{content:"\f21d\f21d"}.fa-duotone.fa-arrow-down-left:after,.fad.fa-arrow-down-left:after{content:"\e091\e091"}.fa-duotone.fa-franc-sign:after,.fad.fa-franc-sign:after{content:"\e18f\e18f"}.fa-duotone.fa-flask-poison:after,.fa-duotone.fa-flask-round-poison:after,.fad.fa-flask-poison:after,.fad.fa-flask-round-poison:after{content:"\f6e0\f6e0"}.fa-duotone.fa-volume-off:after,.fad.fa-volume-off:after{content:"\f026\f026"}.fa-duotone.fa-book-circle-arrow-right:after,.fad.fa-book-circle-arrow-right:after{content:"\e0bc\e0bc"}.fa-duotone.fa-chart-user:after,.fa-duotone.fa-user-chart:after,.fad.fa-chart-user:after,.fad.fa-user-chart:after{content:"\f6a3\f6a3"}.fa-duotone.fa-american-sign-language-interpreting:after,.fa-duotone.fa-asl-interpreting:after,.fa-duotone.fa-hands-american-sign-language-interpreting:after,.fa-duotone.fa-hands-asl-interpreting:after,.fad.fa-american-sign-language-interpreting:after,.fad.fa-asl-interpreting:after,.fad.fa-hands-american-sign-language-interpreting:after,.fad.fa-hands-asl-interpreting:after{content:"\f2a3\f2a3"}.fa-duotone.fa-presentation-screen:after,.fa-duotone.fa-presentation:after,.fad.fa-presentation-screen:after,.fad.fa-presentation:after{content:"\f685\f685"}.fa-duotone.fa-circle-bolt:after,.fad.fa-circle-bolt:after{content:"\e0fe\e0fe"}.fa-duotone.fa-face-smile-halo:after,.fad.fa-face-smile-halo:after{content:"\e38f\e38f"}.fa-duotone.fa-cart-circle-arrow-down:after,.fad.fa-cart-circle-arrow-down:after{content:"\e3ef\e3ef"}.fa-duotone.fa-house-person-arrive:after,.fa-duotone.fa-house-person-return:after,.fa-duotone.fa-house-return:after,.fad.fa-house-person-arrive:after,.fad.fa-house-person-return:after,.fad.fa-house-return:after{content:"\e011\e011"}.fa-duotone.fa-comment-alt-times:after,.fa-duotone.fa-message-times:after,.fa-duotone.fa-message-xmark:after,.fad.fa-comment-alt-times:after,.fad.fa-message-times:after,.fad.fa-message-xmark:after{content:"\f4ab\f4ab"}.fa-duotone.fa-file-award:after,.fa-duotone.fa-file-certificate:after,.fad.fa-file-award:after,.fad.fa-file-certificate:after{content:"\f5f3\f5f3"}.fa-duotone.fa-user-doctor-hair-long:after,.fad.fa-user-doctor-hair-long:after{content:"\e459\e459"}.fa-duotone.fa-camera-home:after,.fa-duotone.fa-camera-security:after,.fad.fa-camera-home:after,.fad.fa-camera-security:after{content:"\f8fe\f8fe"}.fa-duotone.fa-cog:after,.fa-duotone.fa-gear:after,.fad.fa-cog:after,.fad.fa-gear:after{content:"\f013\f013"}.fa-duotone.fa-droplet-slash:after,.fa-duotone.fa-tint-slash:after,.fad.fa-droplet-slash:after,.fad.fa-tint-slash:after{content:"\f5c7\f5c7"}.fa-duotone.fa-book-heart:after,.fad.fa-book-heart:after{content:"\f499\f499"}.fa-duotone.fa-mosque:after,.fad.fa-mosque:after{content:"\f678\f678"}.fa-duotone.fa-duck:after,.fad.fa-duck:after{content:"\f6d8\f6d8"}.fa-duotone.fa-mosquito:after,.fad.fa-mosquito:after{content:"\e52b\e52b"}.fa-duotone.fa-star-of-david:after,.fad.fa-star-of-david:after{content:"\f69a\f69a"}.fa-duotone.fa-flag-alt:after,.fa-duotone.fa-flag-swallowtail:after,.fad.fa-flag-alt:after,.fad.fa-flag-swallowtail:after{content:"\f74c\f74c"}.fa-duotone.fa-person-military-rifle:after,.fad.fa-person-military-rifle:after{content:"\e54b\e54b"}.fa-duotone.fa-car-garage:after,.fad.fa-car-garage:after{content:"\f5e2\f5e2"}.fa-duotone.fa-cart-shopping:after,.fa-duotone.fa-shopping-cart:after,.fad.fa-cart-shopping:after,.fad.fa-shopping-cart:after{content:"\f07a\f07a"}.fa-duotone.fa-book-font:after,.fad.fa-book-font:after{content:"\e0bf\e0bf"}.fa-duotone.fa-shield-plus:after,.fad.fa-shield-plus:after{content:"\e24a\e24a"}.fa-duotone.fa-vials:after,.fad.fa-vials:after{content:"\f493\f493"}.fa-duotone.fa-eye-dropper-full:after,.fad.fa-eye-dropper-full:after{content:"\e172\e172"}.fa-duotone.fa-distribute-spacing-horizontal:after,.fad.fa-distribute-spacing-horizontal:after{content:"\e365\e365"}.fa-duotone.fa-tablet-rugged:after,.fad.fa-tablet-rugged:after{content:"\f48f\f48f"}.fa-duotone.fa-temperature-frigid:after,.fa-duotone.fa-temperature-snow:after,.fad.fa-temperature-frigid:after,.fad.fa-temperature-snow:after{content:"\f768\f768"}.fa-duotone.fa-moped:after,.fad.fa-moped:after{content:"\e3b9\e3b9"}.fa-duotone.fa-face-smile-plus:after,.fa-duotone.fa-smile-plus:after,.fad.fa-face-smile-plus:after,.fad.fa-smile-plus:after{content:"\f5b9\f5b9"}.fa-duotone.fa-radio-alt:after,.fa-duotone.fa-radio-tuner:after,.fad.fa-radio-alt:after,.fad.fa-radio-tuner:after{content:"\f8d8\f8d8"}.fa-duotone.fa-face-swear:after,.fad.fa-face-swear:after{content:"\e399\e399"}.fa-duotone.fa-water-arrow-down:after,.fa-duotone.fa-water-lower:after,.fad.fa-water-arrow-down:after,.fad.fa-water-lower:after{content:"\f774\f774"}.fa-duotone.fa-scanner-touchscreen:after,.fad.fa-scanner-touchscreen:after{content:"\f48a\f48a"}.fa-duotone.fa-circle-7:after,.fad.fa-circle-7:after{content:"\e0f4\e0f4"}.fa-duotone.fa-plug-circle-plus:after,.fad.fa-plug-circle-plus:after{content:"\e55f\e55f"}.fa-duotone.fa-person-ski-jumping:after,.fa-duotone.fa-ski-jump:after,.fad.fa-person-ski-jumping:after,.fad.fa-ski-jump:after{content:"\f7c7\f7c7"}.fa-duotone.fa-place-of-worship:after,.fad.fa-place-of-worship:after{content:"\f67f\f67f"}.fa-duotone.fa-water-arrow-up:after,.fa-duotone.fa-water-rise:after,.fad.fa-water-arrow-up:after,.fad.fa-water-rise:after{content:"\f775\f775"}.fa-duotone.fa-waveform-lines:after,.fa-duotone.fa-waveform-path:after,.fad.fa-waveform-lines:after,.fad.fa-waveform-path:after{content:"\f8f2\f8f2"}.fa-duotone.fa-split:after,.fad.fa-split:after{content:"\e254\e254"}.fa-duotone.fa-film-canister:after,.fa-duotone.fa-film-cannister:after,.fad.fa-film-canister:after,.fad.fa-film-cannister:after{content:"\f8b7\f8b7"}.fa-duotone.fa-folder-times:after,.fa-duotone.fa-folder-xmark:after,.fad.fa-folder-times:after,.fad.fa-folder-xmark:after{content:"\f65f\f65f"}.fa-duotone.fa-toilet-paper-alt:after,.fa-duotone.fa-toilet-paper-blank:after,.fad.fa-toilet-paper-alt:after,.fad.fa-toilet-paper-blank:after{content:"\f71f\f71f"}.fa-duotone.fa-tablet-android-alt:after,.fa-duotone.fa-tablet-screen:after,.fad.fa-tablet-android-alt:after,.fad.fa-tablet-screen:after{content:"\f3fc\f3fc"}.fa-duotone.fa-hexagon-vertical-nft-slanted:after,.fad.fa-hexagon-vertical-nft-slanted:after{content:"\e506\e506"}.fa-duotone.fa-folder-music:after,.fad.fa-folder-music:after{content:"\e18d\e18d"}.fa-duotone.fa-desktop-medical:after,.fa-duotone.fa-display-medical:after,.fad.fa-desktop-medical:after,.fad.fa-display-medical:after{content:"\e166\e166"}.fa-duotone.fa-share-all:after,.fad.fa-share-all:after{content:"\f367\f367"}.fa-duotone.fa-peapod:after,.fad.fa-peapod:after{content:"\e31c\e31c"}.fa-duotone.fa-chess-clock:after,.fad.fa-chess-clock:after{content:"\f43d\f43d"}.fa-duotone.fa-axe:after,.fad.fa-axe:after{content:"\f6b2\f6b2"}.fa-duotone.fa-square-d:after,.fad.fa-square-d:after{content:"\e268\e268"}.fa-duotone.fa-grip-vertical:after,.fad.fa-grip-vertical:after{content:"\f58e\f58e"}.fa-duotone.fa-mobile-signal-out:after,.fad.fa-mobile-signal-out:after{content:"\e1f0\e1f0"}.fa-duotone.fa-arrow-turn-up:after,.fa-duotone.fa-level-up:after,.fad.fa-arrow-turn-up:after,.fad.fa-level-up:after{content:"\f148\f148"}.fa-duotone.fa-u:after,.fad.fa-u:after{content:"\55\55"}.fa-duotone.fa-arrow-up-from-dotted-line:after,.fad.fa-arrow-up-from-dotted-line:after{content:"\e09b\e09b"}.fa-duotone.fa-square-root-alt:after,.fa-duotone.fa-square-root-variable:after,.fad.fa-square-root-alt:after,.fad.fa-square-root-variable:after{content:"\f698\f698"}.fa-duotone.fa-light-switch-on:after,.fad.fa-light-switch-on:after{content:"\e019\e019"}.fa-duotone.fa-arrow-down-arrow-up:after,.fa-duotone.fa-sort-alt:after,.fad.fa-arrow-down-arrow-up:after,.fad.fa-sort-alt:after{content:"\f883\f883"}.fa-duotone.fa-raindrops:after,.fad.fa-raindrops:after{content:"\f75c\f75c"}.fa-duotone.fa-dash:after,.fa-duotone.fa-minus-large:after,.fad.fa-dash:after,.fad.fa-minus-large:after{content:"\e404\e404"}.fa-duotone.fa-clock-four:after,.fa-duotone.fa-clock:after,.fad.fa-clock-four:after,.fad.fa-clock:after{content:"\f017\f017"}.fa-duotone.fa-input-numeric:after,.fad.fa-input-numeric:after{content:"\e1bd\e1bd"}.fa-duotone.fa-truck-tow:after,.fad.fa-truck-tow:after{content:"\e2b8\e2b8"}.fa-duotone.fa-backward-step:after,.fa-duotone.fa-step-backward:after,.fad.fa-backward-step:after,.fad.fa-step-backward:after{content:"\f048\f048"}.fa-duotone.fa-pallet:after,.fad.fa-pallet:after{content:"\f482\f482"}.fa-duotone.fa-car-bolt:after,.fad.fa-car-bolt:after{content:"\e341\e341"}.fa-duotone.fa-arrows-maximize:after,.fa-duotone.fa-expand-arrows:after,.fad.fa-arrows-maximize:after,.fad.fa-expand-arrows:after{content:"\f31d\f31d"}.fa-duotone.fa-faucet:after,.fad.fa-faucet:after{content:"\e005\e005"}.fa-duotone.fa-cloud-sleet:after,.fad.fa-cloud-sleet:after{content:"\f741\f741"}.fa-duotone.fa-lamp-street:after,.fad.fa-lamp-street:after{content:"\e1c5\e1c5"}.fa-duotone.fa-list-radio:after,.fad.fa-list-radio:after{content:"\e1d0\e1d0"}.fa-duotone.fa-pen-nib-slash:after,.fad.fa-pen-nib-slash:after{content:"\e4a1\e4a1"}.fa-duotone.fa-baseball-bat-ball:after,.fad.fa-baseball-bat-ball:after{content:"\f432\f432"}.fa-duotone.fa-square-up-left:after,.fad.fa-square-up-left:after{content:"\e282\e282"}.fa-duotone.fa-overline:after,.fad.fa-overline:after{content:"\f876\f876"}.fa-duotone.fa-s:after,.fad.fa-s:after{content:"\53\53"}.fa-duotone.fa-timeline:after,.fad.fa-timeline:after{content:"\e29c\e29c"}.fa-duotone.fa-keyboard:after,.fad.fa-keyboard:after{content:"\f11c\f11c"}.fa-duotone.fa-arrows-from-dotted-line:after,.fad.fa-arrows-from-dotted-line:after{content:"\e0a3\e0a3"}.fa-duotone.fa-usb-drive:after,.fad.fa-usb-drive:after{content:"\f8e9\f8e9"}.fa-duotone.fa-ballot:after,.fad.fa-ballot:after{content:"\f732\f732"}.fa-duotone.fa-caret-down:after,.fad.fa-caret-down:after{content:"\f0d7\f0d7"}.fa-duotone.fa-location-dot-slash:after,.fa-duotone.fa-map-marker-alt-slash:after,.fad.fa-location-dot-slash:after,.fad.fa-map-marker-alt-slash:after{content:"\f605\f605"}.fa-duotone.fa-cards:after,.fad.fa-cards:after{content:"\e3ed\e3ed"}.fa-duotone.fa-clinic-medical:after,.fa-duotone.fa-house-chimney-medical:after,.fad.fa-clinic-medical:after,.fad.fa-house-chimney-medical:after{content:"\f7f2\f7f2"}.fa-duotone.fa-boxing-glove:after,.fa-duotone.fa-glove-boxing:after,.fad.fa-boxing-glove:after,.fad.fa-glove-boxing:after{content:"\f438\f438"}.fa-duotone.fa-temperature-3:after,.fa-duotone.fa-temperature-three-quarters:after,.fa-duotone.fa-thermometer-3:after,.fa-duotone.fa-thermometer-three-quarters:after,.fad.fa-temperature-3:after,.fad.fa-temperature-three-quarters:after,.fad.fa-thermometer-3:after,.fad.fa-thermometer-three-quarters:after{content:"\f2c8\f2c8"}.fa-duotone.fa-bell-school:after,.fad.fa-bell-school:after{content:"\f5d5\f5d5"}.fa-duotone.fa-mobile-android-alt:after,.fa-duotone.fa-mobile-screen:after,.fad.fa-mobile-android-alt:after,.fad.fa-mobile-screen:after{content:"\f3cf\f3cf"}.fa-duotone.fa-plane-up:after,.fad.fa-plane-up:after{content:"\e22d\e22d"}.fa-duotone.fa-folder-heart:after,.fad.fa-folder-heart:after{content:"\e189\e189"}.fa-duotone.fa-circle-location-arrow:after,.fa-duotone.fa-location-circle:after,.fad.fa-circle-location-arrow:after,.fad.fa-location-circle:after{content:"\f602\f602"}.fa-duotone.fa-face-head-bandage:after,.fad.fa-face-head-bandage:after{content:"\e37a\e37a"}.fa-duotone.fa-maki-roll:after,.fa-duotone.fa-makizushi:after,.fa-duotone.fa-sushi-roll:after,.fad.fa-maki-roll:after,.fad.fa-makizushi:after,.fad.fa-sushi-roll:after{content:"\e48b\e48b"}.fa-duotone.fa-car-bump:after,.fad.fa-car-bump:after{content:"\f5e0\f5e0"}.fa-duotone.fa-piggy-bank:after,.fad.fa-piggy-bank:after{content:"\f4d3\f4d3"}.fa-duotone.fa-racquet:after,.fad.fa-racquet:after{content:"\f45a\f45a"}.fa-duotone.fa-car-mirrors:after,.fad.fa-car-mirrors:after{content:"\e343\e343"}.fa-duotone.fa-industry-alt:after,.fa-duotone.fa-industry-windows:after,.fad.fa-industry-alt:after,.fad.fa-industry-windows:after{content:"\f3b3\f3b3"}.fa-duotone.fa-bolt-auto:after,.fad.fa-bolt-auto:after{content:"\e0b6\e0b6"}.fa-duotone.fa-battery-3:after,.fa-duotone.fa-battery-half:after,.fad.fa-battery-3:after,.fad.fa-battery-half:after{content:"\f242\f242"}.fa-duotone.fa-flux-capacitor:after,.fad.fa-flux-capacitor:after{content:"\f8ba\f8ba"}.fa-duotone.fa-mountain-city:after,.fad.fa-mountain-city:after{content:"\e52e\e52e"}.fa-duotone.fa-coins:after,.fad.fa-coins:after{content:"\f51e\f51e"}.fa-duotone.fa-honey-pot:after,.fad.fa-honey-pot:after{content:"\e418\e418"}.fa-duotone.fa-olive:after,.fad.fa-olive:after{content:"\e316\e316"}.fa-duotone.fa-khanda:after,.fad.fa-khanda:after{content:"\f66d\f66d"}.fa-duotone.fa-filter-list:after,.fad.fa-filter-list:after{content:"\e17c\e17c"}.fa-duotone.fa-outlet:after,.fad.fa-outlet:after{content:"\e01c\e01c"}.fa-duotone.fa-sliders-h:after,.fa-duotone.fa-sliders:after,.fad.fa-sliders-h:after,.fad.fa-sliders:after{content:"\f1de\f1de"}.fa-duotone.fa-cauldron:after,.fad.fa-cauldron:after{content:"\f6bf\f6bf"}.fa-duotone.fa-people:after,.fad.fa-people:after{content:"\e216\e216"}.fa-duotone.fa-folder-tree:after,.fad.fa-folder-tree:after{content:"\f802\f802"}.fa-duotone.fa-network-wired:after,.fad.fa-network-wired:after{content:"\f6ff\f6ff"}.fa-duotone.fa-croissant:after,.fad.fa-croissant:after{content:"\f7f6\f7f6"}.fa-duotone.fa-map-pin:after,.fad.fa-map-pin:after{content:"\f276\f276"}.fa-duotone.fa-hamsa:after,.fad.fa-hamsa:after{content:"\f665\f665"}.fa-duotone.fa-cent-sign:after,.fad.fa-cent-sign:after{content:"\e3f5\e3f5"}.fa-duotone.fa-swords-laser:after,.fad.fa-swords-laser:after{content:"\e03d\e03d"}.fa-duotone.fa-flask:after,.fad.fa-flask:after{content:"\f0c3\f0c3"}.fa-duotone.fa-person-pregnant:after,.fad.fa-person-pregnant:after{content:"\e31e\e31e"}.fa-duotone.fa-square-u:after,.fad.fa-square-u:after{content:"\e281\e281"}.fa-duotone.fa-wand-sparkles:after,.fad.fa-wand-sparkles:after{content:"\f72b\f72b"}.fa-duotone.fa-router:after,.fad.fa-router:after{content:"\f8da\f8da"}.fa-duotone.fa-ellipsis-v:after,.fa-duotone.fa-ellipsis-vertical:after,.fad.fa-ellipsis-v:after,.fad.fa-ellipsis-vertical:after{content:"\f142\f142"}.fa-duotone.fa-sword-laser-alt:after,.fad.fa-sword-laser-alt:after{content:"\e03c\e03c"}.fa-duotone.fa-ticket:after,.fad.fa-ticket:after{content:"\f145\f145"}.fa-duotone.fa-power-off:after,.fad.fa-power-off:after{content:"\f011\f011"}.fa-duotone.fa-coin:after,.fad.fa-coin:after{content:"\f85c\f85c"}.fa-duotone.fa-laptop-slash:after,.fad.fa-laptop-slash:after{content:"\e1c7\e1c7"}.fa-duotone.fa-long-arrow-alt-right:after,.fa-duotone.fa-right-long:after,.fad.fa-long-arrow-alt-right:after,.fad.fa-right-long:after{content:"\f30b\f30b"}.fa-duotone.fa-circle-b:after,.fad.fa-circle-b:after{content:"\e0fd\e0fd"}.fa-duotone.fa-person-dress-simple:after,.fad.fa-person-dress-simple:after{content:"\e21c\e21c"}.fa-duotone.fa-pipe-collar:after,.fad.fa-pipe-collar:after{content:"\e437\e437"}.fa-duotone.fa-lights-holiday:after,.fad.fa-lights-holiday:after{content:"\f7b2\f7b2"}.fa-duotone.fa-citrus:after,.fad.fa-citrus:after{content:"\e2f4\e2f4"}.fa-duotone.fa-flag-usa:after,.fad.fa-flag-usa:after{content:"\f74d\f74d"}.fa-duotone.fa-laptop-file:after,.fad.fa-laptop-file:after{content:"\e51d\e51d"}.fa-duotone.fa-teletype:after,.fa-duotone.fa-tty:after,.fad.fa-teletype:after,.fad.fa-tty:after{content:"\f1e4\f1e4"}.fa-duotone.fa-chart-tree-map:after,.fad.fa-chart-tree-map:after{content:"\e0ea\e0ea"}.fa-duotone.fa-diagram-next:after,.fad.fa-diagram-next:after{content:"\e476\e476"}.fa-duotone.fa-person-rifle:after,.fad.fa-person-rifle:after{content:"\e54e\e54e"}.fa-duotone.fa-clock-five-thirty:after,.fad.fa-clock-five-thirty:after{content:"\e34a\e34a"}.fa-duotone.fa-pipe-valve:after,.fad.fa-pipe-valve:after{content:"\e439\e439"}.fa-duotone.fa-arrow-up-from-arc:after,.fad.fa-arrow-up-from-arc:after{content:"\e4b4\e4b4"}.fa-duotone.fa-face-spiral-eyes:after,.fad.fa-face-spiral-eyes:after{content:"\e485\e485"}.fa-duotone.fa-compress-wide:after,.fad.fa-compress-wide:after{content:"\f326\f326"}.fa-duotone.fa-circle-phone-hangup:after,.fa-duotone.fa-phone-circle-down:after,.fad.fa-circle-phone-hangup:after,.fad.fa-phone-circle-down:after{content:"\e11d\e11d"}.fa-duotone.fa-gear-complex-code:after,.fad.fa-gear-complex-code:after{content:"\e5eb\e5eb"}.fa-duotone.fa-house-medical-circle-exclamation:after,.fad.fa-house-medical-circle-exclamation:after{content:"\e512\e512"}.fa-duotone.fa-badminton:after,.fad.fa-badminton:after{content:"\e33a\e33a"}.fa-duotone.fa-closed-captioning:after,.fad.fa-closed-captioning:after{content:"\f20a\f20a"}.fa-duotone.fa-hiking:after,.fa-duotone.fa-person-hiking:after,.fad.fa-hiking:after,.fad.fa-person-hiking:after{content:"\f6ec\f6ec"}.fa-duotone.fa-arrow-alt-from-left:after,.fa-duotone.fa-right-from-line:after,.fad.fa-arrow-alt-from-left:after,.fad.fa-right-from-line:after{content:"\f347\f347"}.fa-duotone.fa-venus-double:after,.fad.fa-venus-double:after{content:"\f226\f226"}.fa-duotone.fa-images:after,.fad.fa-images:after{content:"\f302\f302"}.fa-duotone.fa-calculator:after,.fad.fa-calculator:after{content:"\f1ec\f1ec"}.fa-duotone.fa-shuttlecock:after,.fad.fa-shuttlecock:after{content:"\f45b\f45b"}.fa-duotone.fa-user-hair:after,.fad.fa-user-hair:after{content:"\e45a\e45a"}.fa-duotone.fa-eye-evil:after,.fad.fa-eye-evil:after{content:"\f6db\f6db"}.fa-duotone.fa-people-pulling:after,.fad.fa-people-pulling:after{content:"\e535\e535"}.fa-duotone.fa-n:after,.fad.fa-n:after{content:"\4e\4e"}.fa-duotone.fa-swap:after,.fad.fa-swap:after{content:"\e609\e609"}.fa-duotone.fa-garage:after,.fad.fa-garage:after{content:"\e009\e009"}.fa-duotone.fa-cable-car:after,.fa-duotone.fa-tram:after,.fad.fa-cable-car:after,.fad.fa-tram:after{content:"\f7da\f7da"}.fa-duotone.fa-shovel-snow:after,.fad.fa-shovel-snow:after{content:"\f7c3\f7c3"}.fa-duotone.fa-cloud-rain:after,.fad.fa-cloud-rain:after{content:"\f73d\f73d"}.fa-duotone.fa-face-lying:after,.fad.fa-face-lying:after{content:"\e37e\e37e"}.fa-duotone.fa-sprinkler:after,.fad.fa-sprinkler:after{content:"\e035\e035"}.fa-duotone.fa-building-circle-xmark:after,.fad.fa-building-circle-xmark:after{content:"\e4d4\e4d4"}.fa-duotone.fa-person-sledding:after,.fa-duotone.fa-sledding:after,.fad.fa-person-sledding:after,.fad.fa-sledding:after{content:"\f7cb\f7cb"}.fa-duotone.fa-game-console-handheld:after,.fad.fa-game-console-handheld:after{content:"\f8bb\f8bb"}.fa-duotone.fa-ship:after,.fad.fa-ship:after{content:"\f21a\f21a"}.fa-duotone.fa-clock-six-thirty:after,.fad.fa-clock-six-thirty:after{content:"\e353\e353"}.fa-duotone.fa-battery-slash:after,.fad.fa-battery-slash:after{content:"\f377\f377"}.fa-duotone.fa-tugrik-sign:after,.fad.fa-tugrik-sign:after{content:"\e2ba\e2ba"}.fa-duotone.fa-arrows-down-to-line:after,.fad.fa-arrows-down-to-line:after{content:"\e4b8\e4b8"}.fa-duotone.fa-download:after,.fad.fa-download:after{content:"\f019\f019"}.fa-duotone.fa-angles-up-down:after,.fad.fa-angles-up-down:after{content:"\e60d\e60d"}.fa-duotone.fa-inventory:after,.fa-duotone.fa-shelves:after,.fad.fa-inventory:after,.fad.fa-shelves:after{content:"\f480\f480"}.fa-duotone.fa-cloud-snow:after,.fad.fa-cloud-snow:after{content:"\f742\f742"}.fa-duotone.fa-face-grin:after,.fa-duotone.fa-grin:after,.fad.fa-face-grin:after,.fad.fa-grin:after{content:"\f580\f580"}.fa-duotone.fa-backspace:after,.fa-duotone.fa-delete-left:after,.fad.fa-backspace:after,.fad.fa-delete-left:after{content:"\f55a\f55a"}.fa-duotone.fa-oven:after,.fad.fa-oven:after{content:"\e01d\e01d"}.fa-duotone.fa-cloud-binary:after,.fad.fa-cloud-binary:after{content:"\e601\e601"}.fa-duotone.fa-eye-dropper-empty:after,.fa-duotone.fa-eye-dropper:after,.fa-duotone.fa-eyedropper:after,.fad.fa-eye-dropper-empty:after,.fad.fa-eye-dropper:after,.fad.fa-eyedropper:after{content:"\f1fb\f1fb"}.fa-duotone.fa-comment-captions:after,.fad.fa-comment-captions:after{content:"\e146\e146"}.fa-duotone.fa-comments-question:after,.fad.fa-comments-question:after{content:"\e14e\e14e"}.fa-duotone.fa-scribble:after,.fad.fa-scribble:after{content:"\e23f\e23f"}.fa-duotone.fa-rotate-exclamation:after,.fad.fa-rotate-exclamation:after{content:"\e23c\e23c"}.fa-duotone.fa-file-circle-check:after,.fad.fa-file-circle-check:after{content:"\e5a0\e5a0"}.fa-duotone.fa-glass:after,.fad.fa-glass:after{content:"\f804\f804"}.fa-duotone.fa-loader:after,.fad.fa-loader:after{content:"\e1d4\e1d4"}.fa-duotone.fa-forward:after,.fad.fa-forward:after{content:"\f04e\f04e"}.fa-duotone.fa-user-pilot:after,.fad.fa-user-pilot:after{content:"\e2c0\e2c0"}.fa-duotone.fa-mobile-android:after,.fa-duotone.fa-mobile-phone:after,.fa-duotone.fa-mobile:after,.fad.fa-mobile-android:after,.fad.fa-mobile-phone:after,.fad.fa-mobile:after{content:"\f3ce\f3ce"}.fa-duotone.fa-code-pull-request-closed:after,.fad.fa-code-pull-request-closed:after{content:"\e3f9\e3f9"}.fa-duotone.fa-face-meh:after,.fa-duotone.fa-meh:after,.fad.fa-face-meh:after,.fad.fa-meh:after{content:"\f11a\f11a"}.fa-duotone.fa-align-center:after,.fad.fa-align-center:after{content:"\f037\f037"}.fa-duotone.fa-book-dead:after,.fa-duotone.fa-book-skull:after,.fad.fa-book-dead:after,.fad.fa-book-skull:after{content:"\f6b7\f6b7"}.fa-duotone.fa-drivers-license:after,.fa-duotone.fa-id-card:after,.fad.fa-drivers-license:after,.fad.fa-id-card:after{content:"\f2c2\f2c2"}.fa-duotone.fa-face-dotted:after,.fad.fa-face-dotted:after{content:"\e47f\e47f"}.fa-duotone.fa-face-worried:after,.fad.fa-face-worried:after{content:"\e3a3\e3a3"}.fa-duotone.fa-dedent:after,.fa-duotone.fa-outdent:after,.fad.fa-dedent:after,.fad.fa-outdent:after{content:"\f03b\f03b"}.fa-duotone.fa-heart-circle-exclamation:after,.fad.fa-heart-circle-exclamation:after{content:"\e4fe\e4fe"}.fa-duotone.fa-home-alt:after,.fa-duotone.fa-home-lg-alt:after,.fa-duotone.fa-home:after,.fa-duotone.fa-house:after,.fad.fa-home-alt:after,.fad.fa-home-lg-alt:after,.fad.fa-home:after,.fad.fa-house:after{content:"\f015\f015"}.fa-duotone.fa-vector-circle:after,.fad.fa-vector-circle:after{content:"\e2c6\e2c6"}.fa-duotone.fa-car-circle-bolt:after,.fad.fa-car-circle-bolt:after{content:"\e342\e342"}.fa-duotone.fa-calendar-week:after,.fad.fa-calendar-week:after{content:"\f784\f784"}.fa-duotone.fa-flying-disc:after,.fad.fa-flying-disc:after{content:"\e3a9\e3a9"}.fa-duotone.fa-laptop-medical:after,.fad.fa-laptop-medical:after{content:"\f812\f812"}.fa-duotone.fa-square-down-right:after,.fad.fa-square-down-right:after{content:"\e26c\e26c"}.fa-duotone.fa-b:after,.fad.fa-b:after{content:"\42\42"}.fa-duotone.fa-seat-airline:after,.fad.fa-seat-airline:after{content:"\e244\e244"}.fa-duotone.fa-eclipse-alt:after,.fa-duotone.fa-moon-over-sun:after,.fad.fa-eclipse-alt:after,.fad.fa-moon-over-sun:after{content:"\f74a\f74a"}.fa-duotone.fa-pipe:after,.fad.fa-pipe:after{content:"\7c\7c"}.fa-duotone.fa-file-medical:after,.fad.fa-file-medical:after{content:"\f477\f477"}.fa-duotone.fa-potato:after,.fad.fa-potato:after{content:"\e440\e440"}.fa-duotone.fa-dice-one:after,.fad.fa-dice-one:after{content:"\f525\f525"}.fa-duotone.fa-circle-a:after,.fad.fa-circle-a:after{content:"\e0f7\e0f7"}.fa-duotone.fa-helmet-battle:after,.fad.fa-helmet-battle:after{content:"\f6eb\f6eb"}.fa-duotone.fa-butter:after,.fad.fa-butter:after{content:"\e3e4\e3e4"}.fa-duotone.fa-blanket-fire:after,.fad.fa-blanket-fire:after{content:"\e3da\e3da"}.fa-duotone.fa-kiwi-bird:after,.fad.fa-kiwi-bird:after{content:"\f535\f535"}.fa-duotone.fa-castle:after,.fad.fa-castle:after{content:"\e0de\e0de"}.fa-duotone.fa-golf-club:after,.fad.fa-golf-club:after{content:"\f451\f451"}.fa-duotone.fa-arrow-right-arrow-left:after,.fa-duotone.fa-exchange:after,.fad.fa-arrow-right-arrow-left:after,.fad.fa-exchange:after{content:"\f0ec\f0ec"}.fa-duotone.fa-redo-alt:after,.fa-duotone.fa-rotate-forward:after,.fa-duotone.fa-rotate-right:after,.fad.fa-redo-alt:after,.fad.fa-rotate-forward:after,.fad.fa-rotate-right:after{content:"\f2f9\f2f9"}.fa-duotone.fa-cutlery:after,.fa-duotone.fa-utensils:after,.fad.fa-cutlery:after,.fad.fa-utensils:after{content:"\f2e7\f2e7"}.fa-duotone.fa-arrow-up-wide-short:after,.fa-duotone.fa-sort-amount-up:after,.fad.fa-arrow-up-wide-short:after,.fad.fa-sort-amount-up:after{content:"\f161\f161"}.fa-duotone.fa-chart-pie-simple-circle-dollar:after,.fad.fa-chart-pie-simple-circle-dollar:after{content:"\e605\e605"}.fa-duotone.fa-balloons:after,.fad.fa-balloons:after{content:"\e2e4\e2e4"}.fa-duotone.fa-mill-sign:after,.fad.fa-mill-sign:after{content:"\e1ed\e1ed"}.fa-duotone.fa-bowl-rice:after,.fad.fa-bowl-rice:after{content:"\e2eb\e2eb"}.fa-duotone.fa-timeline-arrow:after,.fad.fa-timeline-arrow:after{content:"\e29d\e29d"}.fa-duotone.fa-skull:after,.fad.fa-skull:after{content:"\f54c\f54c"}.fa-duotone.fa-game-board-alt:after,.fa-duotone.fa-game-board-simple:after,.fad.fa-game-board-alt:after,.fad.fa-game-board-simple:after{content:"\f868\f868"}.fa-duotone.fa-circle-video:after,.fa-duotone.fa-video-circle:after,.fad.fa-circle-video:after,.fad.fa-video-circle:after{content:"\e12b\e12b"}.fa-duotone.fa-chart-scatter-bubble:after,.fad.fa-chart-scatter-bubble:after{content:"\e0e9\e0e9"}.fa-duotone.fa-house-turret:after,.fad.fa-house-turret:after{content:"\e1b4\e1b4"}.fa-duotone.fa-banana:after,.fad.fa-banana:after{content:"\e2e5\e2e5"}.fa-duotone.fa-hand-holding-skull:after,.fad.fa-hand-holding-skull:after{content:"\e1a4\e1a4"}.fa-duotone.fa-people-dress:after,.fad.fa-people-dress:after{content:"\e217\e217"}.fa-duotone.fa-couch-small:after,.fa-duotone.fa-loveseat:after,.fad.fa-couch-small:after,.fad.fa-loveseat:after{content:"\f4cc\f4cc"}.fa-duotone.fa-broadcast-tower:after,.fa-duotone.fa-tower-broadcast:after,.fad.fa-broadcast-tower:after,.fad.fa-tower-broadcast:after{content:"\f519\f519"}.fa-duotone.fa-truck-pickup:after,.fad.fa-truck-pickup:after{content:"\f63c\f63c"}.fa-duotone.fa-block-quote:after,.fad.fa-block-quote:after{content:"\e0b5\e0b5"}.fa-duotone.fa-long-arrow-alt-up:after,.fa-duotone.fa-up-long:after,.fad.fa-long-arrow-alt-up:after,.fad.fa-up-long:after{content:"\f30c\f30c"}.fa-duotone.fa-stop:after,.fad.fa-stop:after{content:"\f04d\f04d"}.fa-duotone.fa-code-merge:after,.fad.fa-code-merge:after{content:"\f387\f387"}.fa-duotone.fa-money-check-dollar-pen:after,.fa-duotone.fa-money-check-edit-alt:after,.fad.fa-money-check-dollar-pen:after,.fad.fa-money-check-edit-alt:after{content:"\f873\f873"}.fa-duotone.fa-arrow-alt-from-bottom:after,.fa-duotone.fa-up-from-line:after,.fad.fa-arrow-alt-from-bottom:after,.fad.fa-up-from-line:after{content:"\f346\f346"}.fa-duotone.fa-upload:after,.fad.fa-upload:after{content:"\f093\f093"}.fa-duotone.fa-hurricane:after,.fad.fa-hurricane:after{content:"\f751\f751"}.fa-duotone.fa-grid-round-2-plus:after,.fad.fa-grid-round-2-plus:after{content:"\e5dc\e5dc"}.fa-duotone.fa-people-pants:after,.fad.fa-people-pants:after{content:"\e219\e219"}.fa-duotone.fa-mound:after,.fad.fa-mound:after{content:"\e52d\e52d"}.fa-duotone.fa-windsock:after,.fad.fa-windsock:after{content:"\f777\f777"}.fa-duotone.fa-circle-half:after,.fad.fa-circle-half:after{content:"\e110\e110"}.fa-duotone.fa-brake-warning:after,.fad.fa-brake-warning:after{content:"\e0c7\e0c7"}.fa-duotone.fa-toilet-portable:after,.fad.fa-toilet-portable:after{content:"\e583\e583"}.fa-duotone.fa-compact-disc:after,.fad.fa-compact-disc:after{content:"\f51f\f51f"}.fa-duotone.fa-file-arrow-down:after,.fa-duotone.fa-file-download:after,.fad.fa-file-arrow-down:after,.fad.fa-file-download:after{content:"\f56d\f56d"}.fa-duotone.fa-sax-hot:after,.fa-duotone.fa-saxophone-fire:after,.fad.fa-sax-hot:after,.fad.fa-saxophone-fire:after{content:"\f8db\f8db"}.fa-duotone.fa-camera-web-slash:after,.fa-duotone.fa-webcam-slash:after,.fad.fa-camera-web-slash:after,.fad.fa-webcam-slash:after{content:"\f833\f833"}.fa-duotone.fa-folder-medical:after,.fad.fa-folder-medical:after{content:"\e18c\e18c"}.fa-duotone.fa-folder-cog:after,.fa-duotone.fa-folder-gear:after,.fad.fa-folder-cog:after,.fad.fa-folder-gear:after{content:"\e187\e187"}.fa-duotone.fa-hand-wave:after,.fad.fa-hand-wave:after{content:"\e1a7\e1a7"}.fa-duotone.fa-arrow-up-arrow-down:after,.fa-duotone.fa-sort-up-down:after,.fad.fa-arrow-up-arrow-down:after,.fad.fa-sort-up-down:after{content:"\e099\e099"}.fa-duotone.fa-caravan:after,.fad.fa-caravan:after{content:"\f8ff\f8ff"}.fa-duotone.fa-shield-cat:after,.fad.fa-shield-cat:after{content:"\e572\e572"}.fa-duotone.fa-comment-alt-slash:after,.fa-duotone.fa-message-slash:after,.fad.fa-comment-alt-slash:after,.fad.fa-message-slash:after{content:"\f4a9\f4a9"}.fa-duotone.fa-bolt:after,.fa-duotone.fa-zap:after,.fad.fa-bolt:after,.fad.fa-zap:after{content:"\f0e7\f0e7"}.fa-duotone.fa-trash-can-check:after,.fad.fa-trash-can-check:after{content:"\e2a9\e2a9"}.fa-duotone.fa-glass-water:after,.fad.fa-glass-water:after{content:"\e4f4\e4f4"}.fa-duotone.fa-oil-well:after,.fad.fa-oil-well:after{content:"\e532\e532"}.fa-duotone.fa-person-simple:after,.fad.fa-person-simple:after{content:"\e220\e220"}.fa-duotone.fa-vault:after,.fad.fa-vault:after{content:"\e2c5\e2c5"}.fa-duotone.fa-mars:after,.fad.fa-mars:after{content:"\f222\f222"}.fa-duotone.fa-toilet:after,.fad.fa-toilet:after{content:"\f7d8\f7d8"}.fa-duotone.fa-plane-circle-xmark:after,.fad.fa-plane-circle-xmark:after{content:"\e557\e557"}.fa-duotone.fa-cny:after,.fa-duotone.fa-jpy:after,.fa-duotone.fa-rmb:after,.fa-duotone.fa-yen-sign:after,.fa-duotone.fa-yen:after,.fad.fa-cny:after,.fad.fa-jpy:after,.fad.fa-rmb:after,.fad.fa-yen-sign:after,.fad.fa-yen:after{content:"\f157\f157"}.fa-duotone.fa-gear-code:after,.fad.fa-gear-code:after{content:"\e5e8\e5e8"}.fa-duotone.fa-notes:after,.fad.fa-notes:after{content:"\e202\e202"}.fa-duotone.fa-rouble:after,.fa-duotone.fa-rub:after,.fa-duotone.fa-ruble-sign:after,.fa-duotone.fa-ruble:after,.fad.fa-rouble:after,.fad.fa-rub:after,.fad.fa-ruble-sign:after,.fad.fa-ruble:after{content:"\f158\f158"}.fa-duotone.fa-trash-arrow-turn-left:after,.fa-duotone.fa-trash-undo:after,.fad.fa-trash-arrow-turn-left:after,.fad.fa-trash-undo:after{content:"\f895\f895"}.fa-duotone.fa-champagne-glass:after,.fa-duotone.fa-glass-champagne:after,.fad.fa-champagne-glass:after,.fad.fa-glass-champagne:after{content:"\f79e\f79e"}.fa-duotone.fa-objects-align-center-horizontal:after,.fad.fa-objects-align-center-horizontal:after{content:"\e3bc\e3bc"}.fa-duotone.fa-sun:after,.fad.fa-sun:after{content:"\f185\f185"}.fa-duotone.fa-trash-alt-slash:after,.fa-duotone.fa-trash-can-slash:after,.fad.fa-trash-alt-slash:after,.fad.fa-trash-can-slash:after{content:"\e2ad\e2ad"}.fa-duotone.fa-screen-users:after,.fa-duotone.fa-users-class:after,.fad.fa-screen-users:after,.fad.fa-users-class:after{content:"\f63d\f63d"}.fa-duotone.fa-guitar:after,.fad.fa-guitar:after{content:"\f7a6\f7a6"}.fa-duotone.fa-arrow-square-left:after,.fa-duotone.fa-square-arrow-left:after,.fad.fa-arrow-square-left:after,.fad.fa-square-arrow-left:after{content:"\f33a\f33a"}.fa-duotone.fa-square-8:after,.fad.fa-square-8:after{content:"\e25d\e25d"}.fa-duotone.fa-face-smile-hearts:after,.fad.fa-face-smile-hearts:after{content:"\e390\e390"}.fa-duotone.fa-brackets-square:after,.fa-duotone.fa-brackets:after,.fad.fa-brackets-square:after,.fad.fa-brackets:after{content:"\f7e9\f7e9"}.fa-duotone.fa-laptop-arrow-down:after,.fad.fa-laptop-arrow-down:after{content:"\e1c6\e1c6"}.fa-duotone.fa-hockey-stick-puck:after,.fad.fa-hockey-stick-puck:after{content:"\e3ae\e3ae"}.fa-duotone.fa-house-tree:after,.fad.fa-house-tree:after{content:"\e1b3\e1b3"}.fa-duotone.fa-signal-2:after,.fa-duotone.fa-signal-fair:after,.fad.fa-signal-2:after,.fad.fa-signal-fair:after{content:"\f68d\f68d"}.fa-duotone.fa-face-laugh-wink:after,.fa-duotone.fa-laugh-wink:after,.fad.fa-face-laugh-wink:after,.fad.fa-laugh-wink:after{content:"\f59c\f59c"}.fa-duotone.fa-circle-dollar:after,.fa-duotone.fa-dollar-circle:after,.fa-duotone.fa-usd-circle:after,.fad.fa-circle-dollar:after,.fad.fa-dollar-circle:after,.fad.fa-usd-circle:after{content:"\f2e8\f2e8"}.fa-duotone.fa-horse-head:after,.fad.fa-horse-head:after{content:"\f7ab\f7ab"}.fa-duotone.fa-arrows-repeat:after,.fa-duotone.fa-repeat-alt:after,.fad.fa-arrows-repeat:after,.fad.fa-repeat-alt:after{content:"\f364\f364"}.fa-duotone.fa-bore-hole:after,.fad.fa-bore-hole:after{content:"\e4c3\e4c3"}.fa-duotone.fa-industry:after,.fad.fa-industry:after{content:"\f275\f275"}.fa-duotone.fa-image-polaroid:after,.fad.fa-image-polaroid:after{content:"\f8c4\f8c4"}.fa-duotone.fa-wave-triangle:after,.fad.fa-wave-triangle:after{content:"\f89a\f89a"}.fa-duotone.fa-person-running-fast:after,.fad.fa-person-running-fast:after{content:"\e5ff\e5ff"}.fa-duotone.fa-arrow-alt-circle-down:after,.fa-duotone.fa-circle-down:after,.fad.fa-arrow-alt-circle-down:after,.fad.fa-circle-down:after{content:"\f358\f358"}.fa-duotone.fa-grill:after,.fad.fa-grill:after{content:"\e5a3\e5a3"}.fa-duotone.fa-arrows-turn-to-dots:after,.fad.fa-arrows-turn-to-dots:after{content:"\e4c1\e4c1"}.fa-duotone.fa-analytics:after,.fa-duotone.fa-chart-mixed:after,.fad.fa-analytics:after,.fad.fa-chart-mixed:after{content:"\f643\f643"}.fa-duotone.fa-florin-sign:after,.fad.fa-florin-sign:after{content:"\e184\e184"}.fa-duotone.fa-arrow-down-short-wide:after,.fa-duotone.fa-sort-amount-desc:after,.fa-duotone.fa-sort-amount-down-alt:after,.fad.fa-arrow-down-short-wide:after,.fad.fa-sort-amount-desc:after,.fad.fa-sort-amount-down-alt:after{content:"\f884\f884"}.fa-duotone.fa-less-than:after,.fad.fa-less-than:after{content:"\3c\3c"}.fa-duotone.fa-desktop-code:after,.fa-duotone.fa-display-code:after,.fad.fa-desktop-code:after,.fad.fa-display-code:after{content:"\e165\e165"}.fa-duotone.fa-face-drooling:after,.fad.fa-face-drooling:after{content:"\e372\e372"}.fa-duotone.fa-oil-temp:after,.fa-duotone.fa-oil-temperature:after,.fad.fa-oil-temp:after,.fad.fa-oil-temperature:after{content:"\f614\f614"}.fa-duotone.fa-question-square:after,.fa-duotone.fa-square-question:after,.fad.fa-question-square:after,.fad.fa-square-question:after{content:"\f2fd\f2fd"}.fa-duotone.fa-air-conditioner:after,.fad.fa-air-conditioner:after{content:"\f8f4\f8f4"}.fa-duotone.fa-angle-down:after,.fad.fa-angle-down:after{content:"\f107\f107"}.fa-duotone.fa-mountains:after,.fad.fa-mountains:after{content:"\f6fd\f6fd"}.fa-duotone.fa-omega:after,.fad.fa-omega:after{content:"\f67a\f67a"}.fa-duotone.fa-car-tunnel:after,.fad.fa-car-tunnel:after{content:"\e4de\e4de"}.fa-duotone.fa-person-dolly-empty:after,.fad.fa-person-dolly-empty:after{content:"\f4d1\f4d1"}.fa-duotone.fa-pan-food:after,.fad.fa-pan-food:after{content:"\e42b\e42b"}.fa-duotone.fa-head-side-cough:after,.fad.fa-head-side-cough:after{content:"\e061\e061"}.fa-duotone.fa-grip-lines:after,.fad.fa-grip-lines:after{content:"\f7a4\f7a4"}.fa-duotone.fa-thumbs-down:after,.fad.fa-thumbs-down:after{content:"\f165\f165"}.fa-duotone.fa-user-lock:after,.fad.fa-user-lock:after{content:"\f502\f502"}.fa-duotone.fa-arrow-right-long:after,.fa-duotone.fa-long-arrow-right:after,.fad.fa-arrow-right-long:after,.fad.fa-long-arrow-right:after{content:"\f178\f178"}.fa-duotone.fa-tickets-airline:after,.fad.fa-tickets-airline:after{content:"\e29b\e29b"}.fa-duotone.fa-anchor-circle-xmark:after,.fad.fa-anchor-circle-xmark:after{content:"\e4ac\e4ac"}.fa-duotone.fa-ellipsis-h:after,.fa-duotone.fa-ellipsis:after,.fad.fa-ellipsis-h:after,.fad.fa-ellipsis:after{content:"\f141\f141"}.fa-duotone.fa-nfc-slash:after,.fad.fa-nfc-slash:after{content:"\e1fc\e1fc"}.fa-duotone.fa-chess-pawn:after,.fad.fa-chess-pawn:after{content:"\f443\f443"}.fa-duotone.fa-first-aid:after,.fa-duotone.fa-kit-medical:after,.fad.fa-first-aid:after,.fad.fa-kit-medical:after{content:"\f479\f479"}.fa-duotone.fa-grid-2-plus:after,.fad.fa-grid-2-plus:after{content:"\e197\e197"}.fa-duotone.fa-bells:after,.fad.fa-bells:after{content:"\f77f\f77f"}.fa-duotone.fa-person-through-window:after,.fad.fa-person-through-window:after{content:"\e5a9\e5a9"}.fa-duotone.fa-toolbox:after,.fad.fa-toolbox:after{content:"\f552\f552"}.fa-duotone.fa-envelope-badge:after,.fa-duotone.fa-envelope-dot:after,.fad.fa-envelope-badge:after,.fad.fa-envelope-dot:after{content:"\e16f\e16f"}.fa-duotone.fa-hands-holding-circle:after,.fad.fa-hands-holding-circle:after{content:"\e4fb\e4fb"}.fa-duotone.fa-bug:after,.fad.fa-bug:after{content:"\f188\f188"}.fa-duotone.fa-bowl-chopsticks:after,.fad.fa-bowl-chopsticks:after{content:"\e2e9\e2e9"}.fa-duotone.fa-credit-card-alt:after,.fa-duotone.fa-credit-card:after,.fad.fa-credit-card-alt:after,.fad.fa-credit-card:after{content:"\f09d\f09d"}.fa-duotone.fa-circle-s:after,.fad.fa-circle-s:after{content:"\e121\e121"}.fa-duotone.fa-box-ballot:after,.fad.fa-box-ballot:after{content:"\f735\f735"}.fa-duotone.fa-automobile:after,.fa-duotone.fa-car:after,.fad.fa-automobile:after,.fad.fa-car:after{content:"\f1b9\f1b9"}.fa-duotone.fa-hand-holding-hand:after,.fad.fa-hand-holding-hand:after{content:"\e4f7\e4f7"}.fa-duotone.fa-user-tie-hair:after,.fad.fa-user-tie-hair:after{content:"\e45f\e45f"}.fa-duotone.fa-podium-star:after,.fad.fa-podium-star:after{content:"\f758\f758"}.fa-duotone.fa-business-front:after,.fa-duotone.fa-party-back:after,.fa-duotone.fa-trian-balbot:after,.fa-duotone.fa-user-hair-mullet:after,.fad.fa-business-front:after,.fad.fa-party-back:after,.fad.fa-trian-balbot:after,.fad.fa-user-hair-mullet:after{content:"\e45c\e45c"}.fa-duotone.fa-microphone-stand:after,.fad.fa-microphone-stand:after{content:"\f8cb\f8cb"}.fa-duotone.fa-book-open-reader:after,.fa-duotone.fa-book-reader:after,.fad.fa-book-open-reader:after,.fad.fa-book-reader:after{content:"\f5da\f5da"}.fa-duotone.fa-family-dress:after,.fad.fa-family-dress:after{content:"\e301\e301"}.fa-duotone.fa-circle-x:after,.fad.fa-circle-x:after{content:"\e12e\e12e"}.fa-duotone.fa-cabin:after,.fad.fa-cabin:after{content:"\e46d\e46d"}.fa-duotone.fa-mountain-sun:after,.fad.fa-mountain-sun:after{content:"\e52f\e52f"}.fa-duotone.fa-chart-simple-horizontal:after,.fad.fa-chart-simple-horizontal:after{content:"\e474\e474"}.fa-duotone.fa-arrows-left-right-to-line:after,.fad.fa-arrows-left-right-to-line:after{content:"\e4ba\e4ba"}.fa-duotone.fa-hand-back-point-left:after,.fad.fa-hand-back-point-left:after{content:"\e19f\e19f"}.fa-duotone.fa-comment-alt-dots:after,.fa-duotone.fa-message-dots:after,.fa-duotone.fa-messaging:after,.fad.fa-comment-alt-dots:after,.fad.fa-message-dots:after,.fad.fa-messaging:after{content:"\f4a3\f4a3"}.fa-duotone.fa-file-heart:after,.fad.fa-file-heart:after{content:"\e176\e176"}.fa-duotone.fa-beer-foam:after,.fa-duotone.fa-beer-mug:after,.fad.fa-beer-foam:after,.fad.fa-beer-mug:after{content:"\e0b3\e0b3"}.fa-duotone.fa-dice-d20:after,.fad.fa-dice-d20:after{content:"\f6cf\f6cf"}.fa-duotone.fa-drone:after,.fad.fa-drone:after{content:"\f85f\f85f"}.fa-duotone.fa-truck-droplet:after,.fad.fa-truck-droplet:after{content:"\e58c\e58c"}.fa-duotone.fa-file-circle-xmark:after,.fad.fa-file-circle-xmark:after{content:"\e5a1\e5a1"}.fa-duotone.fa-temperature-arrow-up:after,.fa-duotone.fa-temperature-up:after,.fad.fa-temperature-arrow-up:after,.fad.fa-temperature-up:after{content:"\e040\e040"}.fa-duotone.fa-medal:after,.fad.fa-medal:after{content:"\f5a2\f5a2"}.fa-duotone.fa-person-fairy:after,.fad.fa-person-fairy:after{content:"\e608\e608"}.fa-duotone.fa-bed:after,.fad.fa-bed:after{content:"\f236\f236"}.fa-duotone.fa-book-copy:after,.fad.fa-book-copy:after{content:"\e0be\e0be"}.fa-duotone.fa-h-square:after,.fa-duotone.fa-square-h:after,.fad.fa-h-square:after,.fad.fa-square-h:after{content:"\f0fd\f0fd"}.fa-duotone.fa-square-c:after,.fad.fa-square-c:after{content:"\e266\e266"}.fa-duotone.fa-clock-two:after,.fad.fa-clock-two:after{content:"\e35a\e35a"}.fa-duotone.fa-square-ellipsis-vertical:after,.fad.fa-square-ellipsis-vertical:after{content:"\e26f\e26f"}.fa-duotone.fa-calendar-users:after,.fad.fa-calendar-users:after{content:"\e5e2\e5e2"}.fa-duotone.fa-podcast:after,.fad.fa-podcast:after{content:"\f2ce\f2ce"}.fa-duotone.fa-bee:after,.fad.fa-bee:after{content:"\e0b2\e0b2"}.fa-duotone.fa-temperature-4:after,.fa-duotone.fa-temperature-full:after,.fa-duotone.fa-thermometer-4:after,.fa-duotone.fa-thermometer-full:after,.fad.fa-temperature-4:after,.fad.fa-temperature-full:after,.fad.fa-thermometer-4:after,.fad.fa-thermometer-full:after{content:"\f2c7\f2c7"}.fa-duotone.fa-bell:after,.fad.fa-bell:after{content:"\f0f3\f0f3"}.fa-duotone.fa-candy-bar:after,.fa-duotone.fa-chocolate-bar:after,.fad.fa-candy-bar:after,.fad.fa-chocolate-bar:after{content:"\e3e8\e3e8"}.fa-duotone.fa-xmark-large:after,.fad.fa-xmark-large:after{content:"\e59b\e59b"}.fa-duotone.fa-pinata:after,.fad.fa-pinata:after{content:"\e3c3\e3c3"}.fa-duotone.fa-arrows-from-line:after,.fad.fa-arrows-from-line:after{content:"\e0a4\e0a4"}.fa-duotone.fa-superscript:after,.fad.fa-superscript:after{content:"\f12b\f12b"}.fa-duotone.fa-bowl-spoon:after,.fad.fa-bowl-spoon:after{content:"\e3e0\e3e0"}.fa-duotone.fa-hexagon-check:after,.fad.fa-hexagon-check:after{content:"\e416\e416"}.fa-duotone.fa-plug-circle-xmark:after,.fad.fa-plug-circle-xmark:after{content:"\e560\e560"}.fa-duotone.fa-star-of-life:after,.fad.fa-star-of-life:after{content:"\f621\f621"}.fa-duotone.fa-phone-slash:after,.fad.fa-phone-slash:after{content:"\f3dd\f3dd"}.fa-duotone.fa-traffic-light-stop:after,.fad.fa-traffic-light-stop:after{content:"\f63a\f63a"}.fa-duotone.fa-paint-roller:after,.fad.fa-paint-roller:after{content:"\f5aa\f5aa"}.fa-duotone.fa-accent-grave:after,.fad.fa-accent-grave:after{content:"\60\60"}.fa-duotone.fa-hands-helping:after,.fa-duotone.fa-handshake-angle:after,.fad.fa-hands-helping:after,.fad.fa-handshake-angle:after{content:"\f4c4\f4c4"}.fa-duotone.fa-circle-0:after,.fad.fa-circle-0:after{content:"\e0ed\e0ed"}.fa-duotone.fa-dial-med-low:after,.fad.fa-dial-med-low:after{content:"\e160\e160"}.fa-duotone.fa-location-dot:after,.fa-duotone.fa-map-marker-alt:after,.fad.fa-location-dot:after,.fad.fa-map-marker-alt:after{content:"\f3c5\f3c5"}.fa-duotone.fa-crab:after,.fad.fa-crab:after{content:"\e3ff\e3ff"}.fa-duotone.fa-box-full:after,.fa-duotone.fa-box-open-full:after,.fad.fa-box-full:after,.fad.fa-box-open-full:after{content:"\f49c\f49c"}.fa-duotone.fa-file:after,.fad.fa-file:after{content:"\f15b\f15b"}.fa-duotone.fa-greater-than:after,.fad.fa-greater-than:after{content:"\3e\3e"}.fa-duotone.fa-quotes:after,.fad.fa-quotes:after{content:"\e234\e234"}.fa-duotone.fa-pretzel:after,.fad.fa-pretzel:after{content:"\e441\e441"}.fa-duotone.fa-person-swimming:after,.fa-duotone.fa-swimmer:after,.fad.fa-person-swimming:after,.fad.fa-swimmer:after{content:"\f5c4\f5c4"}.fa-duotone.fa-arrow-down:after,.fad.fa-arrow-down:after{content:"\f063\f063"}.fa-duotone.fa-user-robot-xmarks:after,.fad.fa-user-robot-xmarks:after{content:"\e4a7\e4a7"}.fa-duotone.fa-comment-alt-quote:after,.fa-duotone.fa-message-quote:after,.fad.fa-comment-alt-quote:after,.fad.fa-message-quote:after{content:"\e1e4\e1e4"}.fa-duotone.fa-candy-corn:after,.fad.fa-candy-corn:after{content:"\f6bd\f6bd"}.fa-duotone.fa-folder-magnifying-glass:after,.fa-duotone.fa-folder-search:after,.fad.fa-folder-magnifying-glass:after,.fad.fa-folder-search:after{content:"\e18b\e18b"}.fa-duotone.fa-notebook:after,.fad.fa-notebook:after{content:"\e201\e201"}.fa-duotone.fa-droplet:after,.fa-duotone.fa-tint:after,.fad.fa-droplet:after,.fad.fa-tint:after{content:"\f043\f043"}.fa-duotone.fa-bullseye-pointer:after,.fad.fa-bullseye-pointer:after{content:"\f649\f649"}.fa-duotone.fa-eraser:after,.fad.fa-eraser:after{content:"\f12d\f12d"}.fa-duotone.fa-hexagon-image:after,.fad.fa-hexagon-image:after{content:"\e504\e504"}.fa-duotone.fa-earth-america:after,.fa-duotone.fa-earth-americas:after,.fa-duotone.fa-earth:after,.fa-duotone.fa-globe-americas:after,.fad.fa-earth-america:after,.fad.fa-earth-americas:after,.fad.fa-earth:after,.fad.fa-globe-americas:after{content:"\f57d\f57d"}.fa-duotone.fa-crate-apple:after,.fad.fa-crate-apple:after{content:"\f6b1\f6b1"}.fa-duotone.fa-apple-crate:after,.fad.fa-apple-crate:after{content:"\f6b1\f6b1"}.fa-duotone.fa-person-burst:after,.fad.fa-person-burst:after{content:"\e53b\e53b"}.fa-duotone.fa-game-board:after,.fad.fa-game-board:after{content:"\f867\f867"}.fa-duotone.fa-hat-chef:after,.fad.fa-hat-chef:after{content:"\f86b\f86b"}.fa-duotone.fa-hand-back-point-right:after,.fad.fa-hand-back-point-right:after{content:"\e1a1\e1a1"}.fa-duotone.fa-dove:after,.fad.fa-dove:after{content:"\f4ba\f4ba"}.fa-duotone.fa-snowflake-droplets:after,.fad.fa-snowflake-droplets:after{content:"\e5c1\e5c1"}.fa-duotone.fa-battery-0:after,.fa-duotone.fa-battery-empty:after,.fad.fa-battery-0:after,.fad.fa-battery-empty:after{content:"\f244\f244"}.fa-duotone.fa-grid-4:after,.fad.fa-grid-4:after{content:"\e198\e198"}.fa-duotone.fa-socks:after,.fad.fa-socks:after{content:"\f696\f696"}.fa-duotone.fa-face-sunglasses:after,.fad.fa-face-sunglasses:after{content:"\e398\e398"}.fa-duotone.fa-inbox:after,.fad.fa-inbox:after{content:"\f01c\f01c"}.fa-duotone.fa-square-0:after,.fad.fa-square-0:after{content:"\e255\e255"}.fa-duotone.fa-section:after,.fad.fa-section:after{content:"\e447\e447"}.fa-duotone.fa-box-up:after,.fa-duotone.fa-square-this-way-up:after,.fad.fa-box-up:after,.fad.fa-square-this-way-up:after{content:"\f49f\f49f"}.fa-duotone.fa-gauge-high:after,.fa-duotone.fa-tachometer-alt-fast:after,.fa-duotone.fa-tachometer-alt:after,.fad.fa-gauge-high:after,.fad.fa-tachometer-alt-fast:after,.fad.fa-tachometer-alt:after{content:"\f625\f625"}.fa-duotone.fa-square-ampersand:after,.fad.fa-square-ampersand:after{content:"\e260\e260"}.fa-duotone.fa-envelope-open-text:after,.fad.fa-envelope-open-text:after{content:"\f658\f658"}.fa-duotone.fa-lamp-desk:after,.fad.fa-lamp-desk:after{content:"\e014\e014"}.fa-duotone.fa-hospital-alt:after,.fa-duotone.fa-hospital-wide:after,.fa-duotone.fa-hospital:after,.fad.fa-hospital-alt:after,.fad.fa-hospital-wide:after,.fad.fa-hospital:after{content:"\f0f8\f0f8"}.fa-duotone.fa-poll-people:after,.fad.fa-poll-people:after{content:"\f759\f759"}.fa-duotone.fa-glass-whiskey-rocks:after,.fa-duotone.fa-whiskey-glass-ice:after,.fad.fa-glass-whiskey-rocks:after,.fad.fa-whiskey-glass-ice:after{content:"\f7a1\f7a1"}.fa-duotone.fa-wine-bottle:after,.fad.fa-wine-bottle:after{content:"\f72f\f72f"}.fa-duotone.fa-chess-rook:after,.fad.fa-chess-rook:after{content:"\f447\f447"}.fa-duotone.fa-user-bounty-hunter:after,.fad.fa-user-bounty-hunter:after{content:"\e2bf\e2bf"}.fa-duotone.fa-bars-staggered:after,.fa-duotone.fa-reorder:after,.fa-duotone.fa-stream:after,.fad.fa-bars-staggered:after,.fad.fa-reorder:after,.fad.fa-stream:after{content:"\f550\f550"}.fa-duotone.fa-diagram-sankey:after,.fad.fa-diagram-sankey:after{content:"\e158\e158"}.fa-duotone.fa-cloud-hail-mixed:after,.fad.fa-cloud-hail-mixed:after{content:"\f73a\f73a"}.fa-duotone.fa-circle-up-left:after,.fad.fa-circle-up-left:after{content:"\e128\e128"}.fa-duotone.fa-dharmachakra:after,.fad.fa-dharmachakra:after{content:"\f655\f655"}.fa-duotone.fa-objects-align-left:after,.fad.fa-objects-align-left:after{content:"\e3be\e3be"}.fa-duotone.fa-oil-can-drip:after,.fad.fa-oil-can-drip:after{content:"\e205\e205"}.fa-duotone.fa-face-smiling-hands:after,.fad.fa-face-smiling-hands:after{content:"\e396\e396"}.fa-duotone.fa-broccoli:after,.fad.fa-broccoli:after{content:"\e3e2\e3e2"}.fa-duotone.fa-route-interstate:after,.fad.fa-route-interstate:after{content:"\f61b\f61b"}.fa-duotone.fa-ear-muffs:after,.fad.fa-ear-muffs:after{content:"\f795\f795"}.fa-duotone.fa-hotdog:after,.fad.fa-hotdog:after{content:"\f80f\f80f"}.fa-duotone.fa-transporter-empty:after,.fad.fa-transporter-empty:after{content:"\e046\e046"}.fa-duotone.fa-blind:after,.fa-duotone.fa-person-walking-with-cane:after,.fad.fa-blind:after,.fad.fa-person-walking-with-cane:after{content:"\f29d\f29d"}.fa-duotone.fa-angle-90:after,.fad.fa-angle-90:after{content:"\e08d\e08d"}.fa-duotone.fa-rectangle-terminal:after,.fad.fa-rectangle-terminal:after{content:"\e236\e236"}.fa-duotone.fa-kite:after,.fad.fa-kite:after{content:"\f6f4\f6f4"}.fa-duotone.fa-drum:after,.fad.fa-drum:after{content:"\f569\f569"}.fa-duotone.fa-scrubber:after,.fad.fa-scrubber:after{content:"\f2f8\f2f8"}.fa-duotone.fa-ice-cream:after,.fad.fa-ice-cream:after{content:"\f810\f810"}.fa-duotone.fa-heart-circle-bolt:after,.fad.fa-heart-circle-bolt:after{content:"\e4fc\e4fc"}.fa-duotone.fa-fish-bones:after,.fad.fa-fish-bones:after{content:"\e304\e304"}.fa-duotone.fa-deer-rudolph:after,.fad.fa-deer-rudolph:after{content:"\f78f\f78f"}.fa-duotone.fa-fax:after,.fad.fa-fax:after{content:"\f1ac\f1ac"}.fa-duotone.fa-paragraph:after,.fad.fa-paragraph:after{content:"\f1dd\f1dd"}.fa-duotone.fa-head-side-heart:after,.fad.fa-head-side-heart:after{content:"\e1aa\e1aa"}.fa-duotone.fa-square-e:after,.fad.fa-square-e:after{content:"\e26d\e26d"}.fa-duotone.fa-meter-fire:after,.fad.fa-meter-fire:after{content:"\e1eb\e1eb"}.fa-duotone.fa-cloud-hail:after,.fad.fa-cloud-hail:after{content:"\f739\f739"}.fa-duotone.fa-check-to-slot:after,.fa-duotone.fa-vote-yea:after,.fad.fa-check-to-slot:after,.fad.fa-vote-yea:after{content:"\f772\f772"}.fa-duotone.fa-money-from-bracket:after,.fad.fa-money-from-bracket:after{content:"\e312\e312"}.fa-duotone.fa-star-half:after,.fad.fa-star-half:after{content:"\f089\f089"}.fa-duotone.fa-car-bus:after,.fad.fa-car-bus:after{content:"\f85a\f85a"}.fa-duotone.fa-speaker:after,.fad.fa-speaker:after{content:"\f8df\f8df"}.fa-duotone.fa-timer:after,.fad.fa-timer:after{content:"\e29e\e29e"}.fa-duotone.fa-boxes-alt:after,.fa-duotone.fa-boxes-stacked:after,.fa-duotone.fa-boxes:after,.fad.fa-boxes-alt:after,.fad.fa-boxes-stacked:after,.fad.fa-boxes:after{content:"\f468\f468"}.fa-duotone.fa-grill-hot:after,.fad.fa-grill-hot:after{content:"\e5a5\e5a5"}.fa-duotone.fa-ballot-check:after,.fad.fa-ballot-check:after{content:"\f733\f733"}.fa-duotone.fa-chain:after,.fa-duotone.fa-link:after,.fad.fa-chain:after,.fad.fa-link:after{content:"\f0c1\f0c1"}.fa-duotone.fa-assistive-listening-systems:after,.fa-duotone.fa-ear-listen:after,.fad.fa-assistive-listening-systems:after,.fad.fa-ear-listen:after{content:"\f2a2\f2a2"}.fa-duotone.fa-file-minus:after,.fad.fa-file-minus:after{content:"\f318\f318"}.fa-duotone.fa-tree-city:after,.fad.fa-tree-city:after{content:"\e587\e587"}.fa-duotone.fa-play:after,.fad.fa-play:after{content:"\f04b\f04b"}.fa-duotone.fa-font:after,.fad.fa-font:after{content:"\f031\f031"}.fa-duotone.fa-coffee-togo:after,.fa-duotone.fa-cup-togo:after,.fad.fa-coffee-togo:after,.fad.fa-cup-togo:after{content:"\f6c5\f6c5"}.fa-duotone.fa-square-down-left:after,.fad.fa-square-down-left:after{content:"\e26b\e26b"}.fa-duotone.fa-burger-lettuce:after,.fad.fa-burger-lettuce:after{content:"\e3e3\e3e3"}.fa-duotone.fa-rupiah-sign:after,.fad.fa-rupiah-sign:after{content:"\e23d\e23d"}.fa-duotone.fa-magnifying-glass:after,.fa-duotone.fa-search:after,.fad.fa-magnifying-glass:after,.fad.fa-search:after{content:"\f002\f002"}.fa-duotone.fa-ping-pong-paddle-ball:after,.fa-duotone.fa-table-tennis-paddle-ball:after,.fa-duotone.fa-table-tennis:after,.fad.fa-ping-pong-paddle-ball:after,.fad.fa-table-tennis-paddle-ball:after,.fad.fa-table-tennis:after{content:"\f45d\f45d"}.fa-duotone.fa-diagnoses:after,.fa-duotone.fa-person-dots-from-line:after,.fad.fa-diagnoses:after,.fad.fa-person-dots-from-line:after{content:"\f470\f470"}.fa-duotone.fa-chevron-double-down:after,.fa-duotone.fa-chevrons-down:after,.fad.fa-chevron-double-down:after,.fad.fa-chevrons-down:after{content:"\f322\f322"}.fa-duotone.fa-trash-can-arrow-up:after,.fa-duotone.fa-trash-restore-alt:after,.fad.fa-trash-can-arrow-up:after,.fad.fa-trash-restore-alt:after{content:"\f82a\f82a"}.fa-duotone.fa-signal-3:after,.fa-duotone.fa-signal-good:after,.fad.fa-signal-3:after,.fad.fa-signal-good:after{content:"\f68e\f68e"}.fa-duotone.fa-location-question:after,.fa-duotone.fa-map-marker-question:after,.fad.fa-location-question:after,.fad.fa-map-marker-question:after{content:"\f60b\f60b"}.fa-duotone.fa-floppy-disk-circle-xmark:after,.fa-duotone.fa-floppy-disk-times:after,.fa-duotone.fa-save-circle-xmark:after,.fa-duotone.fa-save-times:after,.fad.fa-floppy-disk-circle-xmark:after,.fad.fa-floppy-disk-times:after,.fad.fa-save-circle-xmark:after,.fad.fa-save-times:after{content:"\e181\e181"}.fa-duotone.fa-naira-sign:after,.fad.fa-naira-sign:after{content:"\e1f6\e1f6"}.fa-duotone.fa-peach:after,.fad.fa-peach:after{content:"\e20b\e20b"}.fa-duotone.fa-taxi-bus:after,.fad.fa-taxi-bus:after{content:"\e298\e298"}.fa-duotone.fa-bracket-curly-left:after,.fa-duotone.fa-bracket-curly:after,.fad.fa-bracket-curly-left:after,.fad.fa-bracket-curly:after{content:"\7b\7b"}.fa-duotone.fa-lobster:after,.fad.fa-lobster:after{content:"\e421\e421"}.fa-duotone.fa-cart-flatbed-empty:after,.fa-duotone.fa-dolly-flatbed-empty:after,.fad.fa-cart-flatbed-empty:after,.fad.fa-dolly-flatbed-empty:after{content:"\f476\f476"}.fa-duotone.fa-colon:after,.fad.fa-colon:after{content:"\3a\3a"}.fa-duotone.fa-cart-arrow-down:after,.fad.fa-cart-arrow-down:after{content:"\f218\f218"}.fa-duotone.fa-wand:after,.fad.fa-wand:after{content:"\f72a\f72a"}.fa-duotone.fa-walkie-talkie:after,.fad.fa-walkie-talkie:after{content:"\f8ef\f8ef"}.fa-duotone.fa-file-edit:after,.fa-duotone.fa-file-pen:after,.fad.fa-file-edit:after,.fad.fa-file-pen:after{content:"\f31c\f31c"}.fa-duotone.fa-receipt:after,.fad.fa-receipt:after{content:"\f543\f543"}.fa-duotone.fa-table-picnic:after,.fad.fa-table-picnic:after{content:"\e32d\e32d"}.fa-duotone.fa-pen-square:after,.fa-duotone.fa-pencil-square:after,.fa-duotone.fa-square-pen:after,.fad.fa-pen-square:after,.fad.fa-pencil-square:after,.fad.fa-square-pen:after{content:"\f14b\f14b"}.fa-duotone.fa-circle-microphone-lines:after,.fa-duotone.fa-microphone-circle-alt:after,.fad.fa-circle-microphone-lines:after,.fad.fa-microphone-circle-alt:after{content:"\e117\e117"}.fa-duotone.fa-desktop-slash:after,.fa-duotone.fa-display-slash:after,.fad.fa-desktop-slash:after,.fad.fa-display-slash:after{content:"\e2fa\e2fa"}.fa-duotone.fa-suitcase-rolling:after,.fad.fa-suitcase-rolling:after{content:"\f5c1\f5c1"}.fa-duotone.fa-person-circle-exclamation:after,.fad.fa-person-circle-exclamation:after{content:"\e53f\e53f"}.fa-duotone.fa-transporter-2:after,.fad.fa-transporter-2:after{content:"\e044\e044"}.fa-duotone.fa-hand-receiving:after,.fa-duotone.fa-hands-holding-diamond:after,.fad.fa-hand-receiving:after,.fad.fa-hands-holding-diamond:after{content:"\f47c\f47c"}.fa-duotone.fa-money-bill-simple-wave:after,.fad.fa-money-bill-simple-wave:after{content:"\e1f2\e1f2"}.fa-duotone.fa-chevron-down:after,.fad.fa-chevron-down:after{content:"\f078\f078"}.fa-duotone.fa-battery-5:after,.fa-duotone.fa-battery-full:after,.fa-duotone.fa-battery:after,.fad.fa-battery-5:after,.fad.fa-battery-full:after,.fad.fa-battery:after{content:"\f240\f240"}.fa-duotone.fa-bell-plus:after,.fad.fa-bell-plus:after{content:"\f849\f849"}.fa-duotone.fa-book-arrow-right:after,.fad.fa-book-arrow-right:after{content:"\e0b9\e0b9"}.fa-duotone.fa-hospitals:after,.fad.fa-hospitals:after{content:"\f80e\f80e"}.fa-duotone.fa-club:after,.fad.fa-club:after{content:"\f327\f327"}.fa-duotone.fa-skull-crossbones:after,.fad.fa-skull-crossbones:after{content:"\f714\f714"}.fa-duotone.fa-dewpoint:after,.fa-duotone.fa-droplet-degree:after,.fad.fa-dewpoint:after,.fad.fa-droplet-degree:after{content:"\f748\f748"}.fa-duotone.fa-code-compare:after,.fad.fa-code-compare:after{content:"\e13a\e13a"}.fa-duotone.fa-list-dots:after,.fa-duotone.fa-list-ul:after,.fad.fa-list-dots:after,.fad.fa-list-ul:after{content:"\f0ca\f0ca"}.fa-duotone.fa-hand-holding-magic:after,.fad.fa-hand-holding-magic:after{content:"\f6e5\f6e5"}.fa-duotone.fa-watermelon-slice:after,.fad.fa-watermelon-slice:after{content:"\e337\e337"}.fa-duotone.fa-circle-ellipsis:after,.fad.fa-circle-ellipsis:after{content:"\e10a\e10a"}.fa-duotone.fa-school-lock:after,.fad.fa-school-lock:after{content:"\e56f\e56f"}.fa-duotone.fa-tower-cell:after,.fad.fa-tower-cell:after{content:"\e585\e585"}.fa-duotone.fa-sd-cards:after,.fad.fa-sd-cards:after{content:"\e240\e240"}.fa-duotone.fa-jug-bottle:after,.fad.fa-jug-bottle:after{content:"\e5fb\e5fb"}.fa-duotone.fa-down-long:after,.fa-duotone.fa-long-arrow-alt-down:after,.fad.fa-down-long:after,.fad.fa-long-arrow-alt-down:after{content:"\f309\f309"}.fa-duotone.fa-envelopes:after,.fad.fa-envelopes:after{content:"\e170\e170"}.fa-duotone.fa-phone-office:after,.fad.fa-phone-office:after{content:"\f67d\f67d"}.fa-duotone.fa-ranking-star:after,.fad.fa-ranking-star:after{content:"\e561\e561"}.fa-duotone.fa-chess-king:after,.fad.fa-chess-king:after{content:"\f43f\f43f"}.fa-duotone.fa-nfc-pen:after,.fad.fa-nfc-pen:after{content:"\e1fa\e1fa"}.fa-duotone.fa-person-harassing:after,.fad.fa-person-harassing:after{content:"\e549\e549"}.fa-duotone.fa-hat-winter:after,.fad.fa-hat-winter:after{content:"\f7a8\f7a8"}.fa-duotone.fa-brazilian-real-sign:after,.fad.fa-brazilian-real-sign:after{content:"\e46c\e46c"}.fa-duotone.fa-landmark-alt:after,.fa-duotone.fa-landmark-dome:after,.fad.fa-landmark-alt:after,.fad.fa-landmark-dome:after{content:"\f752\f752"}.fa-duotone.fa-bone-break:after,.fad.fa-bone-break:after{content:"\f5d8\f5d8"}.fa-duotone.fa-arrow-up:after,.fad.fa-arrow-up:after{content:"\f062\f062"}.fa-duotone.fa-down-from-dotted-line:after,.fad.fa-down-from-dotted-line:after{content:"\e407\e407"}.fa-duotone.fa-television:after,.fa-duotone.fa-tv-alt:after,.fa-duotone.fa-tv:after,.fad.fa-television:after,.fad.fa-tv-alt:after,.fad.fa-tv:after{content:"\f26c\f26c"}.fa-duotone.fa-border-left:after,.fad.fa-border-left:after{content:"\f84f\f84f"}.fa-duotone.fa-circle-divide:after,.fad.fa-circle-divide:after{content:"\e106\e106"}.fa-duotone.fa-shrimp:after,.fad.fa-shrimp:after{content:"\e448\e448"}.fa-duotone.fa-list-check:after,.fa-duotone.fa-tasks:after,.fad.fa-list-check:after,.fad.fa-tasks:after{content:"\f0ae\f0ae"}.fa-duotone.fa-diagram-subtask:after,.fad.fa-diagram-subtask:after{content:"\e479\e479"}.fa-duotone.fa-jug-detergent:after,.fad.fa-jug-detergent:after{content:"\e519\e519"}.fa-duotone.fa-circle-user:after,.fa-duotone.fa-user-circle:after,.fad.fa-circle-user:after,.fad.fa-user-circle:after{content:"\f2bd\f2bd"}.fa-duotone.fa-square-y:after,.fad.fa-square-y:after{content:"\e287\e287"}.fa-duotone.fa-user-doctor-hair:after,.fad.fa-user-doctor-hair:after{content:"\e458\e458"}.fa-duotone.fa-planet-ringed:after,.fad.fa-planet-ringed:after{content:"\e020\e020"}.fa-duotone.fa-mushroom:after,.fad.fa-mushroom:after{content:"\e425\e425"}.fa-duotone.fa-user-shield:after,.fad.fa-user-shield:after{content:"\f505\f505"}.fa-duotone.fa-megaphone:after,.fad.fa-megaphone:after{content:"\f675\f675"}.fa-duotone.fa-wreath-laurel:after,.fad.fa-wreath-laurel:after{content:"\e5d2\e5d2"}.fa-duotone.fa-circle-exclamation-check:after,.fad.fa-circle-exclamation-check:after{content:"\e10d\e10d"}.fa-duotone.fa-wind:after,.fad.fa-wind:after{content:"\f72e\f72e"}.fa-duotone.fa-box-dollar:after,.fa-duotone.fa-box-usd:after,.fad.fa-box-dollar:after,.fad.fa-box-usd:after{content:"\f4a0\f4a0"}.fa-duotone.fa-car-burst:after,.fa-duotone.fa-car-crash:after,.fad.fa-car-burst:after,.fad.fa-car-crash:after{content:"\f5e1\f5e1"}.fa-duotone.fa-y:after,.fad.fa-y:after{content:"\59\59"}.fa-duotone.fa-user-headset:after,.fad.fa-user-headset:after{content:"\f82d\f82d"}.fa-duotone.fa-arrows-retweet:after,.fa-duotone.fa-retweet-alt:after,.fad.fa-arrows-retweet:after,.fad.fa-retweet-alt:after{content:"\f361\f361"}.fa-duotone.fa-person-snowboarding:after,.fa-duotone.fa-snowboarding:after,.fad.fa-person-snowboarding:after,.fad.fa-snowboarding:after{content:"\f7ce\f7ce"}.fa-duotone.fa-chevron-square-right:after,.fa-duotone.fa-square-chevron-right:after,.fad.fa-chevron-square-right:after,.fad.fa-square-chevron-right:after{content:"\f32b\f32b"}.fa-duotone.fa-lacrosse-stick-ball:after,.fad.fa-lacrosse-stick-ball:after{content:"\e3b6\e3b6"}.fa-duotone.fa-shipping-fast:after,.fa-duotone.fa-truck-fast:after,.fad.fa-shipping-fast:after,.fad.fa-truck-fast:after{content:"\f48b\f48b"}.fa-duotone.fa-user-magnifying-glass:after,.fad.fa-user-magnifying-glass:after{content:"\e5c5\e5c5"}.fa-duotone.fa-star-sharp:after,.fad.fa-star-sharp:after{content:"\e28b\e28b"}.fa-duotone.fa-comment-heart:after,.fad.fa-comment-heart:after{content:"\e5c8\e5c8"}.fa-duotone.fa-circle-1:after,.fad.fa-circle-1:after{content:"\e0ee\e0ee"}.fa-duotone.fa-circle-star:after,.fa-duotone.fa-star-circle:after,.fad.fa-circle-star:after,.fad.fa-star-circle:after{content:"\e123\e123"}.fa-duotone.fa-fish:after,.fad.fa-fish:after{content:"\f578\f578"}.fa-duotone.fa-cloud-fog:after,.fa-duotone.fa-fog:after,.fad.fa-cloud-fog:after,.fad.fa-fog:after{content:"\f74e\f74e"}.fa-duotone.fa-waffle:after,.fad.fa-waffle:after{content:"\e466\e466"}.fa-duotone.fa-music-alt:after,.fa-duotone.fa-music-note:after,.fad.fa-music-alt:after,.fad.fa-music-note:after{content:"\f8cf\f8cf"}.fa-duotone.fa-hexagon-exclamation:after,.fad.fa-hexagon-exclamation:after{content:"\e417\e417"}.fa-duotone.fa-cart-shopping-fast:after,.fad.fa-cart-shopping-fast:after{content:"\e0dc\e0dc"}.fa-duotone.fa-object-union:after,.fad.fa-object-union:after{content:"\e49f\e49f"}.fa-duotone.fa-user-graduate:after,.fad.fa-user-graduate:after{content:"\f501\f501"}.fa-duotone.fa-starfighter:after,.fad.fa-starfighter:after{content:"\e037\e037"}.fa-duotone.fa-adjust:after,.fa-duotone.fa-circle-half-stroke:after,.fad.fa-adjust:after,.fad.fa-circle-half-stroke:after{content:"\f042\f042"}.fa-duotone.fa-arrow-right-long-to-line:after,.fad.fa-arrow-right-long-to-line:after{content:"\e3d5\e3d5"}.fa-duotone.fa-arrow-square-down:after,.fa-duotone.fa-square-arrow-down:after,.fad.fa-arrow-square-down:after,.fad.fa-square-arrow-down:after{content:"\f339\f339"}.fa-duotone.fa-diamond-half-stroke:after,.fad.fa-diamond-half-stroke:after{content:"\e5b8\e5b8"}.fa-duotone.fa-clapperboard:after,.fad.fa-clapperboard:after{content:"\e131\e131"}.fa-duotone.fa-chevron-square-left:after,.fa-duotone.fa-square-chevron-left:after,.fad.fa-chevron-square-left:after,.fad.fa-square-chevron-left:after{content:"\f32a\f32a"}.fa-duotone.fa-phone-intercom:after,.fad.fa-phone-intercom:after{content:"\e434\e434"}.fa-duotone.fa-chain-horizontal:after,.fa-duotone.fa-link-horizontal:after,.fad.fa-chain-horizontal:after,.fad.fa-link-horizontal:after{content:"\e1cb\e1cb"}.fa-duotone.fa-mango:after,.fad.fa-mango:after{content:"\e30f\e30f"}.fa-duotone.fa-music-alt-slash:after,.fa-duotone.fa-music-note-slash:after,.fad.fa-music-alt-slash:after,.fad.fa-music-note-slash:after{content:"\f8d0\f8d0"}.fa-duotone.fa-circle-radiation:after,.fa-duotone.fa-radiation-alt:after,.fad.fa-circle-radiation:after,.fad.fa-radiation-alt:after{content:"\f7ba\f7ba"}.fa-duotone.fa-face-tongue-sweat:after,.fad.fa-face-tongue-sweat:after{content:"\e39e\e39e"}.fa-duotone.fa-globe-stand:after,.fad.fa-globe-stand:after{content:"\f5f6\f5f6"}.fa-duotone.fa-baseball-ball:after,.fa-duotone.fa-baseball:after,.fad.fa-baseball-ball:after,.fad.fa-baseball:after{content:"\f433\f433"}.fa-duotone.fa-circle-p:after,.fad.fa-circle-p:after{content:"\e11a\e11a"}.fa-duotone.fa-award-simple:after,.fad.fa-award-simple:after{content:"\e0ab\e0ab"}.fa-duotone.fa-jet-fighter-up:after,.fad.fa-jet-fighter-up:after{content:"\e518\e518"}.fa-duotone.fa-diagram-project:after,.fa-duotone.fa-project-diagram:after,.fad.fa-diagram-project:after,.fad.fa-project-diagram:after{content:"\f542\f542"}.fa-duotone.fa-pedestal:after,.fad.fa-pedestal:after{content:"\e20d\e20d"}.fa-duotone.fa-chart-pyramid:after,.fad.fa-chart-pyramid:after{content:"\e0e6\e0e6"}.fa-duotone.fa-sidebar:after,.fad.fa-sidebar:after{content:"\e24e\e24e"}.fa-duotone.fa-frosty-head:after,.fa-duotone.fa-snowman-head:after,.fad.fa-frosty-head:after,.fad.fa-snowman-head:after{content:"\f79b\f79b"}.fa-duotone.fa-copy:after,.fad.fa-copy:after{content:"\f0c5\f0c5"}.fa-duotone.fa-burger-glass:after,.fad.fa-burger-glass:after{content:"\e0ce\e0ce"}.fa-duotone.fa-volume-mute:after,.fa-duotone.fa-volume-times:after,.fa-duotone.fa-volume-xmark:after,.fad.fa-volume-mute:after,.fad.fa-volume-times:after,.fad.fa-volume-xmark:after{content:"\f6a9\f6a9"}.fa-duotone.fa-hand-sparkles:after,.fad.fa-hand-sparkles:after{content:"\e05d\e05d"}.fa-duotone.fa-bars-filter:after,.fad.fa-bars-filter:after{content:"\e0ad\e0ad"}.fa-duotone.fa-paintbrush-pencil:after,.fad.fa-paintbrush-pencil:after{content:"\e206\e206"}.fa-duotone.fa-party-bell:after,.fad.fa-party-bell:after{content:"\e31a\e31a"}.fa-duotone.fa-user-vneck-hair:after,.fad.fa-user-vneck-hair:after{content:"\e462\e462"}.fa-duotone.fa-jack-o-lantern:after,.fad.fa-jack-o-lantern:after{content:"\f30e\f30e"}.fa-duotone.fa-grip-horizontal:after,.fa-duotone.fa-grip:after,.fad.fa-grip-horizontal:after,.fad.fa-grip:after{content:"\f58d\f58d"}.fa-duotone.fa-share-from-square:after,.fa-duotone.fa-share-square:after,.fad.fa-share-from-square:after,.fad.fa-share-square:after{content:"\f14d\f14d"}.fa-duotone.fa-keynote:after,.fad.fa-keynote:after{content:"\f66c\f66c"}.fa-duotone.fa-child-combatant:after,.fa-duotone.fa-child-rifle:after,.fad.fa-child-combatant:after,.fad.fa-child-rifle:after{content:"\e4e0\e4e0"}.fa-duotone.fa-gun:after,.fad.fa-gun:after{content:"\e19b\e19b"}.fa-duotone.fa-phone-square:after,.fa-duotone.fa-square-phone:after,.fad.fa-phone-square:after,.fad.fa-square-phone:after{content:"\f098\f098"}.fa-duotone.fa-hat-beach:after,.fad.fa-hat-beach:after{content:"\e606\e606"}.fa-duotone.fa-add:after,.fa-duotone.fa-plus:after,.fad.fa-add:after,.fad.fa-plus:after{content:"\2b\2b"}.fa-duotone.fa-expand:after,.fad.fa-expand:after{content:"\f065\f065"}.fa-duotone.fa-computer:after,.fad.fa-computer:after{content:"\e4e5\e4e5"}.fa-duotone.fa-fort:after,.fad.fa-fort:after{content:"\e486\e486"}.fa-duotone.fa-cloud-check:after,.fad.fa-cloud-check:after{content:"\e35c\e35c"}.fa-duotone.fa-close:after,.fa-duotone.fa-multiply:after,.fa-duotone.fa-remove:after,.fa-duotone.fa-times:after,.fa-duotone.fa-xmark:after,.fad.fa-close:after,.fad.fa-multiply:after,.fad.fa-remove:after,.fad.fa-times:after,.fad.fa-xmark:after{content:"\f00d\f00d"}.fa-duotone.fa-face-smirking:after,.fad.fa-face-smirking:after{content:"\e397\e397"}.fa-duotone.fa-arrows-up-down-left-right:after,.fa-duotone.fa-arrows:after,.fad.fa-arrows-up-down-left-right:after,.fad.fa-arrows:after{content:"\f047\f047"}.fa-duotone.fa-chalkboard-teacher:after,.fa-duotone.fa-chalkboard-user:after,.fad.fa-chalkboard-teacher:after,.fad.fa-chalkboard-user:after{content:"\f51c\f51c"}.fa-duotone.fa-rhombus:after,.fad.fa-rhombus:after{content:"\e23b\e23b"}.fa-duotone.fa-claw-marks:after,.fad.fa-claw-marks:after{content:"\f6c2\f6c2"}.fa-duotone.fa-peso-sign:after,.fad.fa-peso-sign:after{content:"\e222\e222"}.fa-duotone.fa-face-smile-tongue:after,.fad.fa-face-smile-tongue:after{content:"\e394\e394"}.fa-duotone.fa-cart-circle-xmark:after,.fad.fa-cart-circle-xmark:after{content:"\e3f4\e3f4"}.fa-duotone.fa-building-shield:after,.fad.fa-building-shield:after{content:"\e4d8\e4d8"}.fa-duotone.fa-circle-phone-flip:after,.fa-duotone.fa-phone-circle-alt:after,.fad.fa-circle-phone-flip:after,.fad.fa-phone-circle-alt:after{content:"\e11c\e11c"}.fa-duotone.fa-baby:after,.fad.fa-baby:after{content:"\f77c\f77c"}.fa-duotone.fa-users-line:after,.fad.fa-users-line:after{content:"\e592\e592"}.fa-duotone.fa-quote-left-alt:after,.fa-duotone.fa-quote-left:after,.fad.fa-quote-left-alt:after,.fad.fa-quote-left:after{content:"\f10d\f10d"}.fa-duotone.fa-tractor:after,.fad.fa-tractor:after{content:"\f722\f722"}.fa-duotone.fa-key-skeleton:after,.fad.fa-key-skeleton:after{content:"\f6f3\f6f3"}.fa-duotone.fa-trash-arrow-up:after,.fa-duotone.fa-trash-restore:after,.fad.fa-trash-arrow-up:after,.fad.fa-trash-restore:after{content:"\f829\f829"}.fa-duotone.fa-arrow-down-up-lock:after,.fad.fa-arrow-down-up-lock:after{content:"\e4b0\e4b0"}.fa-duotone.fa-arrow-down-to-bracket:after,.fad.fa-arrow-down-to-bracket:after{content:"\e094\e094"}.fa-duotone.fa-lines-leaning:after,.fad.fa-lines-leaning:after{content:"\e51e\e51e"}.fa-duotone.fa-square-q:after,.fad.fa-square-q:after{content:"\e27b\e27b"}.fa-duotone.fa-ruler-combined:after,.fad.fa-ruler-combined:after{content:"\f546\f546"}.fa-duotone.fa-icons-alt:after,.fa-duotone.fa-symbols:after,.fad.fa-icons-alt:after,.fad.fa-symbols:after{content:"\f86e\f86e"}.fa-duotone.fa-copyright:after,.fad.fa-copyright:after{content:"\f1f9\f1f9"}.fa-duotone.fa-flask-gear:after,.fad.fa-flask-gear:after{content:"\e5f1\e5f1"}.fa-duotone.fa-highlighter-line:after,.fad.fa-highlighter-line:after{content:"\e1af\e1af"}.fa-duotone.fa-bracket-left:after,.fa-duotone.fa-bracket-square:after,.fa-duotone.fa-bracket:after,.fad.fa-bracket-left:after,.fad.fa-bracket-square:after,.fad.fa-bracket:after{content:"\5b\5b"}.fa-duotone.fa-island-tree-palm:after,.fa-duotone.fa-island-tropical:after,.fad.fa-island-tree-palm:after,.fad.fa-island-tropical:after{content:"\f811\f811"}.fa-duotone.fa-arrow-from-left:after,.fa-duotone.fa-arrow-right-from-line:after,.fad.fa-arrow-from-left:after,.fad.fa-arrow-right-from-line:after{content:"\f343\f343"}.fa-duotone.fa-h2:after,.fad.fa-h2:after{content:"\f314\f314"}.fa-duotone.fa-equals:after,.fad.fa-equals:after{content:"\3d\3d"}.fa-duotone.fa-cake-slice:after,.fa-duotone.fa-shortcake:after,.fad.fa-cake-slice:after,.fad.fa-shortcake:after{content:"\e3e5\e3e5"}.fa-duotone.fa-peanut:after,.fad.fa-peanut:after{content:"\e430\e430"}.fa-duotone.fa-wrench-simple:after,.fad.fa-wrench-simple:after{content:"\e2d1\e2d1"}.fa-duotone.fa-blender:after,.fad.fa-blender:after{content:"\f517\f517"}.fa-duotone.fa-teeth:after,.fad.fa-teeth:after{content:"\f62e\f62e"}.fa-duotone.fa-tally-2:after,.fad.fa-tally-2:after{content:"\e295\e295"}.fa-duotone.fa-ils:after,.fa-duotone.fa-shekel-sign:after,.fa-duotone.fa-shekel:after,.fa-duotone.fa-sheqel-sign:after,.fa-duotone.fa-sheqel:after,.fad.fa-ils:after,.fad.fa-shekel-sign:after,.fad.fa-shekel:after,.fad.fa-sheqel-sign:after,.fad.fa-sheqel:after{content:"\f20b\f20b"}.fa-duotone.fa-cars:after,.fad.fa-cars:after{content:"\f85b\f85b"}.fa-duotone.fa-axe-battle:after,.fad.fa-axe-battle:after{content:"\f6b3\f6b3"}.fa-duotone.fa-user-hair-long:after,.fad.fa-user-hair-long:after{content:"\e45b\e45b"}.fa-duotone.fa-map:after,.fad.fa-map:after{content:"\f279\f279"}.fa-duotone.fa-arrow-left-from-arc:after,.fad.fa-arrow-left-from-arc:after{content:"\e615\e615"}.fa-duotone.fa-file-circle-info:after,.fad.fa-file-circle-info:after{content:"\e493\e493"}.fa-duotone.fa-face-disappointed:after,.fad.fa-face-disappointed:after{content:"\e36f\e36f"}.fa-duotone.fa-lasso-sparkles:after,.fad.fa-lasso-sparkles:after{content:"\e1c9\e1c9"}.fa-duotone.fa-clock-eleven:after,.fad.fa-clock-eleven:after{content:"\e347\e347"}.fa-duotone.fa-rocket:after,.fad.fa-rocket:after{content:"\f135\f135"}.fa-duotone.fa-siren-on:after,.fad.fa-siren-on:after{content:"\e02e\e02e"}.fa-duotone.fa-clock-ten:after,.fad.fa-clock-ten:after{content:"\e354\e354"}.fa-duotone.fa-candle-holder:after,.fad.fa-candle-holder:after{content:"\f6bc\f6bc"}.fa-duotone.fa-video-arrow-down-left:after,.fad.fa-video-arrow-down-left:after{content:"\e2c8\e2c8"}.fa-duotone.fa-photo-film:after,.fa-duotone.fa-photo-video:after,.fad.fa-photo-film:after,.fad.fa-photo-video:after{content:"\f87c\f87c"}.fa-duotone.fa-floppy-disk-circle-arrow-right:after,.fa-duotone.fa-save-circle-arrow-right:after,.fad.fa-floppy-disk-circle-arrow-right:after,.fad.fa-save-circle-arrow-right:after{content:"\e180\e180"}.fa-duotone.fa-folder-minus:after,.fad.fa-folder-minus:after{content:"\f65d\f65d"}.fa-duotone.fa-planet-moon:after,.fad.fa-planet-moon:after{content:"\e01f\e01f"}.fa-duotone.fa-face-eyes-xmarks:after,.fad.fa-face-eyes-xmarks:after{content:"\e374\e374"}.fa-duotone.fa-chart-scatter:after,.fad.fa-chart-scatter:after{content:"\f7ee\f7ee"}.fa-duotone.fa-display-arrow-down:after,.fad.fa-display-arrow-down:after{content:"\e164\e164"}.fa-duotone.fa-store:after,.fad.fa-store:after{content:"\f54e\f54e"}.fa-duotone.fa-arrow-trend-up:after,.fad.fa-arrow-trend-up:after{content:"\e098\e098"}.fa-duotone.fa-plug-circle-minus:after,.fad.fa-plug-circle-minus:after{content:"\e55e\e55e"}.fa-duotone.fa-olive-branch:after,.fad.fa-olive-branch:after{content:"\e317\e317"}.fa-duotone.fa-angle:after,.fad.fa-angle:after{content:"\e08c\e08c"}.fa-duotone.fa-vacuum-robot:after,.fad.fa-vacuum-robot:after{content:"\e04e\e04e"}.fa-duotone.fa-sign-hanging:after,.fa-duotone.fa-sign:after,.fad.fa-sign-hanging:after,.fad.fa-sign:after{content:"\f4d9\f4d9"}.fa-duotone.fa-square-divide:after,.fad.fa-square-divide:after{content:"\e26a\e26a"}.fa-duotone.fa-signal-stream-slash:after,.fad.fa-signal-stream-slash:after{content:"\e250\e250"}.fa-duotone.fa-bezier-curve:after,.fad.fa-bezier-curve:after{content:"\f55b\f55b"}.fa-duotone.fa-eye-dropper-half:after,.fad.fa-eye-dropper-half:after{content:"\e173\e173"}.fa-duotone.fa-store-lock:after,.fad.fa-store-lock:after{content:"\e4a6\e4a6"}.fa-duotone.fa-bell-slash:after,.fad.fa-bell-slash:after{content:"\f1f6\f1f6"}.fa-duotone.fa-cloud-bolt-sun:after,.fa-duotone.fa-thunderstorm-sun:after,.fad.fa-cloud-bolt-sun:after,.fad.fa-thunderstorm-sun:after{content:"\f76e\f76e"}.fa-duotone.fa-camera-slash:after,.fad.fa-camera-slash:after{content:"\e0d9\e0d9"}.fa-duotone.fa-comment-quote:after,.fad.fa-comment-quote:after{content:"\e14c\e14c"}.fa-duotone.fa-tablet-android:after,.fa-duotone.fa-tablet:after,.fad.fa-tablet-android:after,.fad.fa-tablet:after{content:"\f3fb\f3fb"}.fa-duotone.fa-school-flag:after,.fad.fa-school-flag:after{content:"\e56e\e56e"}.fa-duotone.fa-message-code:after,.fad.fa-message-code:after{content:"\e1df\e1df"}.fa-duotone.fa-glass-half-empty:after,.fa-duotone.fa-glass-half-full:after,.fa-duotone.fa-glass-half:after,.fad.fa-glass-half-empty:after,.fad.fa-glass-half-full:after,.fad.fa-glass-half:after{content:"\e192\e192"}.fa-duotone.fa-fill:after,.fad.fa-fill:after{content:"\f575\f575"}.fa-duotone.fa-comment-alt-minus:after,.fa-duotone.fa-message-minus:after,.fad.fa-comment-alt-minus:after,.fad.fa-message-minus:after{content:"\f4a7\f4a7"}.fa-duotone.fa-angle-up:after,.fad.fa-angle-up:after{content:"\f106\f106"}.fa-duotone.fa-dinosaur:after,.fad.fa-dinosaur:after{content:"\e5fe\e5fe"}.fa-duotone.fa-drumstick-bite:after,.fad.fa-drumstick-bite:after{content:"\f6d7\f6d7"}.fa-duotone.fa-chain-horizontal-slash:after,.fa-duotone.fa-link-horizontal-slash:after,.fad.fa-chain-horizontal-slash:after,.fad.fa-link-horizontal-slash:after{content:"\e1cc\e1cc"}.fa-duotone.fa-holly-berry:after,.fad.fa-holly-berry:after{content:"\f7aa\f7aa"}.fa-duotone.fa-nose:after,.fad.fa-nose:after{content:"\e5bd\e5bd"}.fa-duotone.fa-arrow-left-to-arc:after,.fad.fa-arrow-left-to-arc:after{content:"\e616\e616"}.fa-duotone.fa-chevron-left:after,.fad.fa-chevron-left:after{content:"\f053\f053"}.fa-duotone.fa-bacteria:after,.fad.fa-bacteria:after{content:"\e059\e059"}.fa-duotone.fa-clouds:after,.fad.fa-clouds:after{content:"\f744\f744"}.fa-duotone.fa-money-bill-simple:after,.fad.fa-money-bill-simple:after{content:"\e1f1\e1f1"}.fa-duotone.fa-hand-lizard:after,.fad.fa-hand-lizard:after{content:"\f258\f258"}.fa-duotone.fa-table-pivot:after,.fad.fa-table-pivot:after{content:"\e291\e291"}.fa-duotone.fa-filter-slash:after,.fad.fa-filter-slash:after{content:"\e17d\e17d"}.fa-duotone.fa-trash-can-arrow-turn-left:after,.fa-duotone.fa-trash-can-undo:after,.fa-duotone.fa-trash-undo-alt:after,.fad.fa-trash-can-arrow-turn-left:after,.fad.fa-trash-can-undo:after,.fad.fa-trash-undo-alt:after{content:"\f896\f896"}.fa-duotone.fa-notdef:after,.fad.fa-notdef:after{content:"\e1fe\e1fe"}.fa-duotone.fa-disease:after,.fad.fa-disease:after{content:"\f7fa\f7fa"}.fa-duotone.fa-person-to-door:after,.fad.fa-person-to-door:after{content:"\e433\e433"}.fa-duotone.fa-turntable:after,.fad.fa-turntable:after{content:"\f8e4\f8e4"}.fa-duotone.fa-briefcase-medical:after,.fad.fa-briefcase-medical:after{content:"\f469\f469"}.fa-duotone.fa-genderless:after,.fad.fa-genderless:after{content:"\f22d\f22d"}.fa-duotone.fa-chevron-right:after,.fad.fa-chevron-right:after{content:"\f054\f054"}.fa-duotone.fa-signal-1:after,.fa-duotone.fa-signal-weak:after,.fad.fa-signal-1:after,.fad.fa-signal-weak:after{content:"\f68c\f68c"}.fa-duotone.fa-clock-five:after,.fad.fa-clock-five:after{content:"\e349\e349"}.fa-duotone.fa-retweet:after,.fad.fa-retweet:after{content:"\f079\f079"}.fa-duotone.fa-car-alt:after,.fa-duotone.fa-car-rear:after,.fad.fa-car-alt:after,.fad.fa-car-rear:after{content:"\f5de\f5de"}.fa-duotone.fa-pump-soap:after,.fad.fa-pump-soap:after{content:"\e06b\e06b"}.fa-duotone.fa-computer-classic:after,.fad.fa-computer-classic:after{content:"\f8b1\f8b1"}.fa-duotone.fa-frame:after,.fad.fa-frame:after{content:"\e495\e495"}.fa-duotone.fa-video-slash:after,.fad.fa-video-slash:after{content:"\f4e2\f4e2"}.fa-duotone.fa-battery-2:after,.fa-duotone.fa-battery-quarter:after,.fad.fa-battery-2:after,.fad.fa-battery-quarter:after{content:"\f243\f243"}.fa-duotone.fa-ellipsis-h-alt:after,.fa-duotone.fa-ellipsis-stroke:after,.fad.fa-ellipsis-h-alt:after,.fad.fa-ellipsis-stroke:after{content:"\f39b\f39b"}.fa-duotone.fa-radio:after,.fad.fa-radio:after{content:"\f8d7\f8d7"}.fa-duotone.fa-baby-carriage:after,.fa-duotone.fa-carriage-baby:after,.fad.fa-baby-carriage:after,.fad.fa-carriage-baby:after{content:"\f77d\f77d"}.fa-duotone.fa-face-expressionless:after,.fad.fa-face-expressionless:after{content:"\e373\e373"}.fa-duotone.fa-down-to-dotted-line:after,.fad.fa-down-to-dotted-line:after{content:"\e408\e408"}.fa-duotone.fa-cloud-music:after,.fad.fa-cloud-music:after{content:"\f8ae\f8ae"}.fa-duotone.fa-traffic-light:after,.fad.fa-traffic-light:after{content:"\f637\f637"}.fa-duotone.fa-cloud-minus:after,.fad.fa-cloud-minus:after{content:"\e35d\e35d"}.fa-duotone.fa-thermometer:after,.fad.fa-thermometer:after{content:"\f491\f491"}.fa-duotone.fa-shield-minus:after,.fad.fa-shield-minus:after{content:"\e249\e249"}.fa-duotone.fa-vr-cardboard:after,.fad.fa-vr-cardboard:after{content:"\f729\f729"}.fa-duotone.fa-car-tilt:after,.fad.fa-car-tilt:after{content:"\f5e5\f5e5"}.fa-duotone.fa-gauge-circle-minus:after,.fad.fa-gauge-circle-minus:after{content:"\e497\e497"}.fa-duotone.fa-brightness-low:after,.fad.fa-brightness-low:after{content:"\e0ca\e0ca"}.fa-duotone.fa-hand-middle-finger:after,.fad.fa-hand-middle-finger:after{content:"\f806\f806"}.fa-duotone.fa-percent:after,.fa-duotone.fa-percentage:after,.fad.fa-percent:after,.fad.fa-percentage:after{content:"\25\25"}.fa-duotone.fa-truck-moving:after,.fad.fa-truck-moving:after{content:"\f4df\f4df"}.fa-duotone.fa-glass-water-droplet:after,.fad.fa-glass-water-droplet:after{content:"\e4f5\e4f5"}.fa-duotone.fa-conveyor-belt:after,.fad.fa-conveyor-belt:after{content:"\f46e\f46e"}.fa-duotone.fa-location-check:after,.fa-duotone.fa-map-marker-check:after,.fad.fa-location-check:after,.fad.fa-map-marker-check:after{content:"\f606\f606"}.fa-duotone.fa-coin-vertical:after,.fad.fa-coin-vertical:after{content:"\e3fd\e3fd"}.fa-duotone.fa-display:after,.fad.fa-display:after{content:"\e163\e163"}.fa-duotone.fa-person-sign:after,.fad.fa-person-sign:after{content:"\f757\f757"}.fa-duotone.fa-face-smile:after,.fa-duotone.fa-smile:after,.fad.fa-face-smile:after,.fad.fa-smile:after{content:"\f118\f118"}.fa-duotone.fa-phone-hangup:after,.fad.fa-phone-hangup:after{content:"\e225\e225"}.fa-duotone.fa-signature-slash:after,.fad.fa-signature-slash:after{content:"\e3cb\e3cb"}.fa-duotone.fa-thumb-tack:after,.fa-duotone.fa-thumbtack:after,.fad.fa-thumb-tack:after,.fad.fa-thumbtack:after{content:"\f08d\f08d"}.fa-duotone.fa-wheat-slash:after,.fad.fa-wheat-slash:after{content:"\e339\e339"}.fa-duotone.fa-trophy:after,.fad.fa-trophy:after{content:"\f091\f091"}.fa-duotone.fa-clouds-sun:after,.fad.fa-clouds-sun:after{content:"\f746\f746"}.fa-duotone.fa-person-praying:after,.fa-duotone.fa-pray:after,.fad.fa-person-praying:after,.fad.fa-pray:after{content:"\f683\f683"}.fa-duotone.fa-hammer:after,.fad.fa-hammer:after{content:"\f6e3\f6e3"}.fa-duotone.fa-face-vomit:after,.fad.fa-face-vomit:after{content:"\e3a0\e3a0"}.fa-duotone.fa-speakers:after,.fad.fa-speakers:after{content:"\f8e0\f8e0"}.fa-duotone.fa-teletype-answer:after,.fa-duotone.fa-tty-answer:after,.fad.fa-teletype-answer:after,.fad.fa-tty-answer:after{content:"\e2b9\e2b9"}.fa-duotone.fa-mug-tea-saucer:after,.fad.fa-mug-tea-saucer:after{content:"\e1f5\e1f5"}.fa-duotone.fa-diagram-lean-canvas:after,.fad.fa-diagram-lean-canvas:after{content:"\e156\e156"}.fa-duotone.fa-alt:after,.fad.fa-alt:after{content:"\e08a\e08a"}.fa-duotone.fa-dial-med-high:after,.fa-duotone.fa-dial:after,.fad.fa-dial-med-high:after,.fad.fa-dial:after{content:"\e15b\e15b"}.fa-duotone.fa-hand-peace:after,.fad.fa-hand-peace:after{content:"\f25b\f25b"}.fa-duotone.fa-circle-trash:after,.fa-duotone.fa-trash-circle:after,.fad.fa-circle-trash:after,.fad.fa-trash-circle:after{content:"\e126\e126"}.fa-duotone.fa-rotate:after,.fa-duotone.fa-sync-alt:after,.fad.fa-rotate:after,.fad.fa-sync-alt:after{content:"\f2f1\f2f1"}.fa-duotone.fa-circle-quarters:after,.fad.fa-circle-quarters:after{content:"\e3f8\e3f8"}.fa-duotone.fa-spinner:after,.fad.fa-spinner:after{content:"\f110\f110"}.fa-duotone.fa-tower-control:after,.fad.fa-tower-control:after{content:"\e2a2\e2a2"}.fa-duotone.fa-arrow-up-triangle-square:after,.fa-duotone.fa-sort-shapes-up:after,.fad.fa-arrow-up-triangle-square:after,.fad.fa-sort-shapes-up:after{content:"\f88a\f88a"}.fa-duotone.fa-whale:after,.fad.fa-whale:after{content:"\f72c\f72c"}.fa-duotone.fa-robot:after,.fad.fa-robot:after{content:"\f544\f544"}.fa-duotone.fa-peace:after,.fad.fa-peace:after{content:"\f67c\f67c"}.fa-duotone.fa-party-horn:after,.fad.fa-party-horn:after{content:"\e31b\e31b"}.fa-duotone.fa-cogs:after,.fa-duotone.fa-gears:after,.fad.fa-cogs:after,.fad.fa-gears:after{content:"\f085\f085"}.fa-duotone.fa-sun-alt:after,.fa-duotone.fa-sun-bright:after,.fad.fa-sun-alt:after,.fad.fa-sun-bright:after{content:"\e28f\e28f"}.fa-duotone.fa-warehouse:after,.fad.fa-warehouse:after{content:"\f494\f494"}.fa-duotone.fa-conveyor-belt-arm:after,.fad.fa-conveyor-belt-arm:after{content:"\e5f8\e5f8"}.fa-duotone.fa-lock-keyhole-open:after,.fa-duotone.fa-lock-open-alt:after,.fad.fa-lock-keyhole-open:after,.fad.fa-lock-open-alt:after{content:"\f3c2\f3c2"}.fa-duotone.fa-box-fragile:after,.fa-duotone.fa-square-fragile:after,.fa-duotone.fa-square-wine-glass-crack:after,.fad.fa-box-fragile:after,.fad.fa-square-fragile:after,.fad.fa-square-wine-glass-crack:after{content:"\f49b\f49b"}.fa-duotone.fa-arrow-up-right-dots:after,.fad.fa-arrow-up-right-dots:after{content:"\e4b7\e4b7"}.fa-duotone.fa-square-n:after,.fad.fa-square-n:after{content:"\e277\e277"}.fa-duotone.fa-splotch:after,.fad.fa-splotch:after{content:"\f5bc\f5bc"}.fa-duotone.fa-face-grin-hearts:after,.fa-duotone.fa-grin-hearts:after,.fad.fa-face-grin-hearts:after,.fad.fa-grin-hearts:after{content:"\f584\f584"}.fa-duotone.fa-meter:after,.fad.fa-meter:after{content:"\e1e8\e1e8"}.fa-duotone.fa-mandolin:after,.fad.fa-mandolin:after{content:"\f6f9\f6f9"}.fa-duotone.fa-dice-four:after,.fad.fa-dice-four:after{content:"\f524\f524"}.fa-duotone.fa-sim-card:after,.fad.fa-sim-card:after{content:"\f7c4\f7c4"}.fa-duotone.fa-transgender-alt:after,.fa-duotone.fa-transgender:after,.fad.fa-transgender-alt:after,.fad.fa-transgender:after{content:"\f225\f225"}.fa-duotone.fa-mercury:after,.fad.fa-mercury:after{content:"\f223\f223"}.fa-duotone.fa-up-from-bracket:after,.fad.fa-up-from-bracket:after{content:"\e590\e590"}.fa-duotone.fa-knife-kitchen:after,.fad.fa-knife-kitchen:after{content:"\f6f5\f6f5"}.fa-duotone.fa-border-right:after,.fad.fa-border-right:after{content:"\f852\f852"}.fa-duotone.fa-arrow-turn-down:after,.fa-duotone.fa-level-down:after,.fad.fa-arrow-turn-down:after,.fad.fa-level-down:after{content:"\f149\f149"}.fa-duotone.fa-spade:after,.fad.fa-spade:after{content:"\f2f4\f2f4"}.fa-duotone.fa-card-spade:after,.fad.fa-card-spade:after{content:"\e3ec\e3ec"}.fa-duotone.fa-line-columns:after,.fad.fa-line-columns:after{content:"\f870\f870"}.fa-duotone.fa-arrow-right-to-line:after,.fa-duotone.fa-arrow-to-right:after,.fad.fa-arrow-right-to-line:after,.fad.fa-arrow-to-right:after{content:"\f340\f340"}.fa-duotone.fa-person-falling-burst:after,.fad.fa-person-falling-burst:after{content:"\e547\e547"}.fa-duotone.fa-flag-pennant:after,.fa-duotone.fa-pennant:after,.fad.fa-flag-pennant:after,.fad.fa-pennant:after{content:"\f456\f456"}.fa-duotone.fa-conveyor-belt-empty:after,.fad.fa-conveyor-belt-empty:after{content:"\e150\e150"}.fa-duotone.fa-user-group-simple:after,.fad.fa-user-group-simple:after{content:"\e603\e603"}.fa-duotone.fa-award:after,.fad.fa-award:after{content:"\f559\f559"}.fa-duotone.fa-ticket-alt:after,.fa-duotone.fa-ticket-simple:after,.fad.fa-ticket-alt:after,.fad.fa-ticket-simple:after{content:"\f3ff\f3ff"}.fa-duotone.fa-building:after,.fad.fa-building:after{content:"\f1ad\f1ad"}.fa-duotone.fa-angle-double-left:after,.fa-duotone.fa-angles-left:after,.fad.fa-angle-double-left:after,.fad.fa-angles-left:after{content:"\f100\f100"}.fa-duotone.fa-camcorder:after,.fa-duotone.fa-video-handheld:after,.fad.fa-camcorder:after,.fad.fa-video-handheld:after{content:"\f8a8\f8a8"}.fa-duotone.fa-pancakes:after,.fad.fa-pancakes:after{content:"\e42d\e42d"}.fa-duotone.fa-album-circle-user:after,.fad.fa-album-circle-user:after{content:"\e48d\e48d"}.fa-duotone.fa-subtitles-slash:after,.fad.fa-subtitles-slash:after{content:"\e610\e610"}.fa-duotone.fa-qrcode:after,.fad.fa-qrcode:after{content:"\f029\f029"}.fa-duotone.fa-dice-d10:after,.fad.fa-dice-d10:after{content:"\f6cd\f6cd"}.fa-duotone.fa-fireplace:after,.fad.fa-fireplace:after{content:"\f79a\f79a"}.fa-duotone.fa-browser:after,.fad.fa-browser:after{content:"\f37e\f37e"}.fa-duotone.fa-pen-paintbrush:after,.fa-duotone.fa-pencil-paintbrush:after,.fad.fa-pen-paintbrush:after,.fad.fa-pencil-paintbrush:after{content:"\f618\f618"}.fa-duotone.fa-fish-cooked:after,.fad.fa-fish-cooked:after{content:"\f7fe\f7fe"}.fa-duotone.fa-chair-office:after,.fad.fa-chair-office:after{content:"\f6c1\f6c1"}.fa-duotone.fa-nesting-dolls:after,.fad.fa-nesting-dolls:after{content:"\e3ba\e3ba"}.fa-duotone.fa-clock-rotate-left:after,.fa-duotone.fa-history:after,.fad.fa-clock-rotate-left:after,.fad.fa-history:after{content:"\f1da\f1da"}.fa-duotone.fa-trumpet:after,.fad.fa-trumpet:after{content:"\f8e3\f8e3"}.fa-duotone.fa-face-grin-beam-sweat:after,.fa-duotone.fa-grin-beam-sweat:after,.fad.fa-face-grin-beam-sweat:after,.fad.fa-grin-beam-sweat:after{content:"\f583\f583"}.fa-duotone.fa-fire-smoke:after,.fad.fa-fire-smoke:after{content:"\f74b\f74b"}.fa-duotone.fa-phone-missed:after,.fad.fa-phone-missed:after{content:"\e226\e226"}.fa-duotone.fa-arrow-right-from-file:after,.fa-duotone.fa-file-export:after,.fad.fa-arrow-right-from-file:after,.fad.fa-file-export:after{content:"\f56e\f56e"}.fa-duotone.fa-shield-blank:after,.fa-duotone.fa-shield:after,.fad.fa-shield-blank:after,.fad.fa-shield:after{content:"\f132\f132"}.fa-duotone.fa-arrow-up-short-wide:after,.fa-duotone.fa-sort-amount-up-alt:after,.fad.fa-arrow-up-short-wide:after,.fad.fa-sort-amount-up-alt:after{content:"\f885\f885"}.fa-duotone.fa-arrows-repeat-1:after,.fa-duotone.fa-repeat-1-alt:after,.fad.fa-arrows-repeat-1:after,.fad.fa-repeat-1-alt:after{content:"\f366\f366"}.fa-duotone.fa-gun-slash:after,.fad.fa-gun-slash:after{content:"\e19c\e19c"}.fa-duotone.fa-avocado:after,.fad.fa-avocado:after{content:"\e0aa\e0aa"}.fa-duotone.fa-binary:after,.fad.fa-binary:after{content:"\e33b\e33b"}.fa-duotone.fa-glasses-alt:after,.fa-duotone.fa-glasses-round:after,.fad.fa-glasses-alt:after,.fad.fa-glasses-round:after{content:"\f5f5\f5f5"}.fa-duotone.fa-phone-plus:after,.fad.fa-phone-plus:after{content:"\f4d2\f4d2"}.fa-duotone.fa-ditto:after,.fad.fa-ditto:after{content:"\22\22"}.fa-duotone.fa-person-seat:after,.fad.fa-person-seat:after{content:"\e21e\e21e"}.fa-duotone.fa-house-medical:after,.fad.fa-house-medical:after{content:"\e3b2\e3b2"}.fa-duotone.fa-golf-ball-tee:after,.fa-duotone.fa-golf-ball:after,.fad.fa-golf-ball-tee:after,.fad.fa-golf-ball:after{content:"\f450\f450"}.fa-duotone.fa-chevron-circle-left:after,.fa-duotone.fa-circle-chevron-left:after,.fad.fa-chevron-circle-left:after,.fad.fa-circle-chevron-left:after{content:"\f137\f137"}.fa-duotone.fa-house-chimney-window:after,.fad.fa-house-chimney-window:after{content:"\e00d\e00d"}.fa-duotone.fa-scythe:after,.fad.fa-scythe:after{content:"\f710\f710"}.fa-duotone.fa-pen-nib:after,.fad.fa-pen-nib:after{content:"\f5ad\f5ad"}.fa-duotone.fa-ban-parking:after,.fa-duotone.fa-parking-circle-slash:after,.fad.fa-ban-parking:after,.fad.fa-parking-circle-slash:after{content:"\f616\f616"}.fa-duotone.fa-tent-arrow-turn-left:after,.fad.fa-tent-arrow-turn-left:after{content:"\e580\e580"}.fa-duotone.fa-face-diagonal-mouth:after,.fad.fa-face-diagonal-mouth:after{content:"\e47e\e47e"}.fa-duotone.fa-diagram-cells:after,.fad.fa-diagram-cells:after{content:"\e475\e475"}.fa-duotone.fa-cricket-bat-ball:after,.fa-duotone.fa-cricket:after,.fad.fa-cricket-bat-ball:after,.fad.fa-cricket:after{content:"\f449\f449"}.fa-duotone.fa-tents:after,.fad.fa-tents:after{content:"\e582\e582"}.fa-duotone.fa-magic:after,.fa-duotone.fa-wand-magic:after,.fad.fa-magic:after,.fad.fa-wand-magic:after{content:"\f0d0\f0d0"}.fa-duotone.fa-dog:after,.fad.fa-dog:after{content:"\f6d3\f6d3"}.fa-duotone.fa-pen-line:after,.fad.fa-pen-line:after{content:"\e212\e212"}.fa-duotone.fa-atom-alt:after,.fa-duotone.fa-atom-simple:after,.fad.fa-atom-alt:after,.fad.fa-atom-simple:after{content:"\f5d3\f5d3"}.fa-duotone.fa-ampersand:after,.fad.fa-ampersand:after{content:"\26\26"}.fa-duotone.fa-carrot:after,.fad.fa-carrot:after{content:"\f787\f787"}.fa-duotone.fa-arrow-from-bottom:after,.fa-duotone.fa-arrow-up-from-line:after,.fad.fa-arrow-from-bottom:after,.fad.fa-arrow-up-from-line:after{content:"\f342\f342"}.fa-duotone.fa-moon:after,.fad.fa-moon:after{content:"\f186\f186"}.fa-duotone.fa-pen-slash:after,.fad.fa-pen-slash:after{content:"\e213\e213"}.fa-duotone.fa-wine-glass-alt:after,.fa-duotone.fa-wine-glass-empty:after,.fad.fa-wine-glass-alt:after,.fad.fa-wine-glass-empty:after{content:"\f5ce\f5ce"}.fa-duotone.fa-square-star:after,.fad.fa-square-star:after{content:"\e27f\e27f"}.fa-duotone.fa-cheese:after,.fad.fa-cheese:after{content:"\f7ef\f7ef"}.fa-duotone.fa-send-backward:after,.fad.fa-send-backward:after{content:"\f87f\f87f"}.fa-duotone.fa-yin-yang:after,.fad.fa-yin-yang:after{content:"\f6ad\f6ad"}.fa-duotone.fa-music:after,.fad.fa-music:after{content:"\f001\f001"}.fa-duotone.fa-compass-slash:after,.fad.fa-compass-slash:after{content:"\f5e9\f5e9"}.fa-duotone.fa-clock-one:after,.fad.fa-clock-one:after{content:"\e34e\e34e"}.fa-duotone.fa-file-music:after,.fad.fa-file-music:after{content:"\f8b6\f8b6"}.fa-duotone.fa-code-commit:after,.fad.fa-code-commit:after{content:"\f386\f386"}.fa-duotone.fa-temperature-low:after,.fad.fa-temperature-low:after{content:"\f76b\f76b"}.fa-duotone.fa-biking:after,.fa-duotone.fa-person-biking:after,.fad.fa-biking:after,.fad.fa-person-biking:after{content:"\f84a\f84a"}.fa-duotone.fa-display-chart-up-circle-currency:after,.fad.fa-display-chart-up-circle-currency:after{content:"\e5e5\e5e5"}.fa-duotone.fa-skeleton:after,.fad.fa-skeleton:after{content:"\f620\f620"}.fa-duotone.fa-circle-g:after,.fad.fa-circle-g:after{content:"\e10f\e10f"}.fa-duotone.fa-circle-arrow-up-left:after,.fad.fa-circle-arrow-up-left:after{content:"\e0fb\e0fb"}.fa-duotone.fa-coin-blank:after,.fad.fa-coin-blank:after{content:"\e3fb\e3fb"}.fa-duotone.fa-broom:after,.fad.fa-broom:after{content:"\f51a\f51a"}.fa-duotone.fa-vacuum:after,.fad.fa-vacuum:after{content:"\e04d\e04d"}.fa-duotone.fa-shield-heart:after,.fad.fa-shield-heart:after{content:"\e574\e574"}.fa-duotone.fa-card-heart:after,.fad.fa-card-heart:after{content:"\e3eb\e3eb"}.fa-duotone.fa-lightbulb-cfl-on:after,.fad.fa-lightbulb-cfl-on:after{content:"\e5a7\e5a7"}.fa-duotone.fa-melon:after,.fad.fa-melon:after{content:"\e310\e310"}.fa-duotone.fa-gopuram:after,.fad.fa-gopuram:after{content:"\f664\f664"}.fa-duotone.fa-earth-oceania:after,.fa-duotone.fa-globe-oceania:after,.fad.fa-earth-oceania:after,.fad.fa-globe-oceania:after{content:"\e47b\e47b"}.fa-duotone.fa-container-storage:after,.fad.fa-container-storage:after{content:"\f4b7\f4b7"}.fa-duotone.fa-face-pouting:after,.fad.fa-face-pouting:after{content:"\e387\e387"}.fa-duotone.fa-square-xmark:after,.fa-duotone.fa-times-square:after,.fa-duotone.fa-xmark-square:after,.fad.fa-square-xmark:after,.fad.fa-times-square:after,.fad.fa-xmark-square:after{content:"\f2d3\f2d3"}.fa-duotone.fa-exploding-head:after,.fa-duotone.fa-face-explode:after,.fad.fa-exploding-head:after,.fad.fa-face-explode:after{content:"\e2fe\e2fe"}.fa-duotone.fa-hashtag:after,.fad.fa-hashtag:after{content:"\23\23"}.fa-duotone.fa-expand-alt:after,.fa-duotone.fa-up-right-and-down-left-from-center:after,.fad.fa-expand-alt:after,.fad.fa-up-right-and-down-left-from-center:after{content:"\f424\f424"}.fa-duotone.fa-oil-can:after,.fad.fa-oil-can:after{content:"\f613\f613"}.fa-duotone.fa-t:after,.fad.fa-t:after{content:"\54\54"}.fa-duotone.fa-transformer-bolt:after,.fad.fa-transformer-bolt:after{content:"\e2a4\e2a4"}.fa-duotone.fa-hippo:after,.fad.fa-hippo:after{content:"\f6ed\f6ed"}.fa-duotone.fa-chart-column:after,.fad.fa-chart-column:after{content:"\e0e3\e0e3"}.fa-duotone.fa-cassette-vhs:after,.fa-duotone.fa-vhs:after,.fad.fa-cassette-vhs:after,.fad.fa-vhs:after{content:"\f8ec\f8ec"}.fa-duotone.fa-infinity:after,.fad.fa-infinity:after{content:"\f534\f534"}.fa-duotone.fa-vial-circle-check:after,.fad.fa-vial-circle-check:after{content:"\e596\e596"}.fa-duotone.fa-chimney:after,.fad.fa-chimney:after{content:"\f78b\f78b"}.fa-duotone.fa-object-intersect:after,.fad.fa-object-intersect:after{content:"\e49d\e49d"}.fa-duotone.fa-person-arrow-down-to-line:after,.fad.fa-person-arrow-down-to-line:after{content:"\e538\e538"}.fa-duotone.fa-voicemail:after,.fad.fa-voicemail:after{content:"\f897\f897"}.fa-duotone.fa-block-brick:after,.fa-duotone.fa-wall-brick:after,.fad.fa-block-brick:after,.fad.fa-wall-brick:after{content:"\e3db\e3db"}.fa-duotone.fa-fan:after,.fad.fa-fan:after{content:"\f863\f863"}.fa-duotone.fa-bags-shopping:after,.fad.fa-bags-shopping:after{content:"\f847\f847"}.fa-duotone.fa-paragraph-left:after,.fa-duotone.fa-paragraph-rtl:after,.fad.fa-paragraph-left:after,.fad.fa-paragraph-rtl:after{content:"\f878\f878"}.fa-duotone.fa-person-walking-luggage:after,.fad.fa-person-walking-luggage:after{content:"\e554\e554"}.fa-duotone.fa-caravan-alt:after,.fa-duotone.fa-caravan-simple:after,.fad.fa-caravan-alt:after,.fad.fa-caravan-simple:after{content:"\e000\e000"}.fa-duotone.fa-turtle:after,.fad.fa-turtle:after{content:"\f726\f726"}.fa-duotone.fa-pencil-mechanical:after,.fad.fa-pencil-mechanical:after{content:"\e5ca\e5ca"}.fa-duotone.fa-arrows-alt-v:after,.fa-duotone.fa-up-down:after,.fad.fa-arrows-alt-v:after,.fad.fa-up-down:after{content:"\f338\f338"}.fa-duotone.fa-cloud-moon-rain:after,.fad.fa-cloud-moon-rain:after{content:"\f73c\f73c"}.fa-duotone.fa-booth-curtain:after,.fad.fa-booth-curtain:after{content:"\f734\f734"}.fa-duotone.fa-calendar:after,.fad.fa-calendar:after{content:"\f133\f133"}.fa-duotone.fa-box-heart:after,.fad.fa-box-heart:after{content:"\f49d\f49d"}.fa-duotone.fa-trailer:after,.fad.fa-trailer:after{content:"\e041\e041"}.fa-duotone.fa-user-doctor-message:after,.fa-duotone.fa-user-md-chat:after,.fad.fa-user-doctor-message:after,.fad.fa-user-md-chat:after{content:"\f82e\f82e"}.fa-duotone.fa-bahai:after,.fa-duotone.fa-haykal:after,.fad.fa-bahai:after,.fad.fa-haykal:after{content:"\f666\f666"}.fa-duotone.fa-lighthouse:after,.fad.fa-lighthouse:after{content:"\e612\e612"}.fa-duotone.fa-amp-guitar:after,.fad.fa-amp-guitar:after{content:"\f8a1\f8a1"}.fa-duotone.fa-sd-card:after,.fad.fa-sd-card:after{content:"\f7c2\f7c2"}.fa-duotone.fa-volume-slash:after,.fad.fa-volume-slash:after{content:"\f2e2\f2e2"}.fa-duotone.fa-border-bottom:after,.fad.fa-border-bottom:after{content:"\f84d\f84d"}.fa-duotone.fa-wifi-1:after,.fa-duotone.fa-wifi-weak:after,.fad.fa-wifi-1:after,.fad.fa-wifi-weak:after{content:"\f6aa\f6aa"}.fa-duotone.fa-dragon:after,.fad.fa-dragon:after{content:"\f6d5\f6d5"}.fa-duotone.fa-shoe-prints:after,.fad.fa-shoe-prints:after{content:"\f54b\f54b"}.fa-duotone.fa-circle-plus:after,.fa-duotone.fa-plus-circle:after,.fad.fa-circle-plus:after,.fad.fa-plus-circle:after{content:"\f055\f055"}.fa-duotone.fa-face-grin-tongue-wink:after,.fa-duotone.fa-grin-tongue-wink:after,.fad.fa-face-grin-tongue-wink:after,.fad.fa-grin-tongue-wink:after{content:"\f58b\f58b"}.fa-duotone.fa-hand-holding:after,.fad.fa-hand-holding:after{content:"\f4bd\f4bd"}.fa-duotone.fa-plug-circle-exclamation:after,.fad.fa-plug-circle-exclamation:after{content:"\e55d\e55d"}.fa-duotone.fa-chain-broken:after,.fa-duotone.fa-chain-slash:after,.fa-duotone.fa-link-slash:after,.fa-duotone.fa-unlink:after,.fad.fa-chain-broken:after,.fad.fa-chain-slash:after,.fad.fa-link-slash:after,.fad.fa-unlink:after{content:"\f127\f127"}.fa-duotone.fa-clone:after,.fad.fa-clone:after{content:"\f24d\f24d"}.fa-duotone.fa-person-walking-arrow-loop-left:after,.fad.fa-person-walking-arrow-loop-left:after{content:"\e551\e551"}.fa-duotone.fa-arrow-up-z-a:after,.fa-duotone.fa-sort-alpha-up-alt:after,.fad.fa-arrow-up-z-a:after,.fad.fa-sort-alpha-up-alt:after{content:"\f882\f882"}.fa-duotone.fa-fire-alt:after,.fa-duotone.fa-fire-flame-curved:after,.fad.fa-fire-alt:after,.fad.fa-fire-flame-curved:after{content:"\f7e4\f7e4"}.fa-duotone.fa-tornado:after,.fad.fa-tornado:after{content:"\f76f\f76f"}.fa-duotone.fa-file-circle-plus:after,.fad.fa-file-circle-plus:after{content:"\e494\e494"}.fa-duotone.fa-delete-right:after,.fad.fa-delete-right:after{content:"\e154\e154"}.fa-duotone.fa-book-quran:after,.fa-duotone.fa-quran:after,.fad.fa-book-quran:after,.fad.fa-quran:after{content:"\f687\f687"}.fa-duotone.fa-circle-quarter:after,.fad.fa-circle-quarter:after{content:"\e11f\e11f"}.fa-duotone.fa-anchor:after,.fad.fa-anchor:after{content:"\f13d\f13d"}.fa-duotone.fa-border-all:after,.fad.fa-border-all:after{content:"\f84c\f84c"}.fa-duotone.fa-function:after,.fad.fa-function:after{content:"\f661\f661"}.fa-duotone.fa-angry:after,.fa-duotone.fa-face-angry:after,.fad.fa-angry:after,.fad.fa-face-angry:after{content:"\f556\f556"}.fa-duotone.fa-people-simple:after,.fad.fa-people-simple:after{content:"\e21b\e21b"}.fa-duotone.fa-cookie-bite:after,.fad.fa-cookie-bite:after{content:"\f564\f564"}.fa-duotone.fa-arrow-trend-down:after,.fad.fa-arrow-trend-down:after{content:"\e097\e097"}.fa-duotone.fa-feed:after,.fa-duotone.fa-rss:after,.fad.fa-feed:after,.fad.fa-rss:after{content:"\f09e\f09e"}.fa-duotone.fa-face-monocle:after,.fad.fa-face-monocle:after{content:"\e380\e380"}.fa-duotone.fa-draw-polygon:after,.fad.fa-draw-polygon:after{content:"\f5ee\f5ee"}.fa-duotone.fa-balance-scale:after,.fa-duotone.fa-scale-balanced:after,.fad.fa-balance-scale:after,.fad.fa-scale-balanced:after{content:"\f24e\f24e"}.fa-duotone.fa-calendar-lines:after,.fa-duotone.fa-calendar-note:after,.fad.fa-calendar-lines:after,.fad.fa-calendar-note:after{content:"\e0d5\e0d5"}.fa-duotone.fa-arrow-down-big-small:after,.fa-duotone.fa-sort-size-down:after,.fad.fa-arrow-down-big-small:after,.fad.fa-sort-size-down:after{content:"\f88c\f88c"}.fa-duotone.fa-gauge-simple-high:after,.fa-duotone.fa-tachometer-fast:after,.fa-duotone.fa-tachometer:after,.fad.fa-gauge-simple-high:after,.fad.fa-tachometer-fast:after,.fad.fa-tachometer:after{content:"\f62a\f62a"}.fa-duotone.fa-do-not-enter:after,.fad.fa-do-not-enter:after{content:"\f5ec\f5ec"}.fa-duotone.fa-shower:after,.fad.fa-shower:after{content:"\f2cc\f2cc"}.fa-duotone.fa-dice-d8:after,.fad.fa-dice-d8:after{content:"\f6d2\f6d2"}.fa-duotone.fa-desktop-alt:after,.fa-duotone.fa-desktop:after,.fad.fa-desktop-alt:after,.fad.fa-desktop:after{content:"\f390\f390"}.fa-duotone.fa-m:after,.fad.fa-m:after{content:"\4d\4d"}.fa-duotone.fa-grip-dots-vertical:after,.fad.fa-grip-dots-vertical:after{content:"\e411\e411"}.fa-duotone.fa-face-viewfinder:after,.fad.fa-face-viewfinder:after{content:"\e2ff\e2ff"}.fa-duotone.fa-creemee:after,.fa-duotone.fa-soft-serve:after,.fad.fa-creemee:after,.fad.fa-soft-serve:after{content:"\e400\e400"}.fa-duotone.fa-h5:after,.fad.fa-h5:after{content:"\e412\e412"}.fa-duotone.fa-hand-back-point-down:after,.fad.fa-hand-back-point-down:after{content:"\e19e\e19e"}.fa-duotone.fa-table-list:after,.fa-duotone.fa-th-list:after,.fad.fa-table-list:after,.fad.fa-th-list:after{content:"\f00b\f00b"}.fa-duotone.fa-comment-sms:after,.fa-duotone.fa-sms:after,.fad.fa-comment-sms:after,.fad.fa-sms:after{content:"\f7cd\f7cd"}.fa-duotone.fa-rectangle-landscape:after,.fa-duotone.fa-rectangle:after,.fad.fa-rectangle-landscape:after,.fad.fa-rectangle:after{content:"\f2fa\f2fa"}.fa-duotone.fa-clipboard-list-check:after,.fad.fa-clipboard-list-check:after{content:"\f737\f737"}.fa-duotone.fa-turkey:after,.fad.fa-turkey:after{content:"\f725\f725"}.fa-duotone.fa-book:after,.fad.fa-book:after{content:"\f02d\f02d"}.fa-duotone.fa-user-plus:after,.fad.fa-user-plus:after{content:"\f234\f234"}.fa-duotone.fa-ice-skate:after,.fad.fa-ice-skate:after{content:"\f7ac\f7ac"}.fa-duotone.fa-check:after,.fad.fa-check:after{content:"\f00c\f00c"}.fa-duotone.fa-battery-4:after,.fa-duotone.fa-battery-three-quarters:after,.fad.fa-battery-4:after,.fad.fa-battery-three-quarters:after{content:"\f241\f241"}.fa-duotone.fa-tomato:after,.fad.fa-tomato:after{content:"\e330\e330"}.fa-duotone.fa-sword-laser:after,.fad.fa-sword-laser:after{content:"\e03b\e03b"}.fa-duotone.fa-house-circle-check:after,.fad.fa-house-circle-check:after{content:"\e509\e509"}.fa-duotone.fa-buildings:after,.fad.fa-buildings:after{content:"\e0cc\e0cc"}.fa-duotone.fa-angle-left:after,.fad.fa-angle-left:after{content:"\f104\f104"}.fa-duotone.fa-cart-flatbed-boxes:after,.fa-duotone.fa-dolly-flatbed-alt:after,.fad.fa-cart-flatbed-boxes:after,.fad.fa-dolly-flatbed-alt:after{content:"\f475\f475"}.fa-duotone.fa-diagram-successor:after,.fad.fa-diagram-successor:after{content:"\e47a\e47a"}.fa-duotone.fa-truck-arrow-right:after,.fad.fa-truck-arrow-right:after{content:"\e58b\e58b"}.fa-duotone.fa-square-w:after,.fad.fa-square-w:after{content:"\e285\e285"}.fa-duotone.fa-arrows-split-up-and-left:after,.fad.fa-arrows-split-up-and-left:after{content:"\e4bc\e4bc"}.fa-duotone.fa-lamp:after,.fad.fa-lamp:after{content:"\f4ca\f4ca"}.fa-duotone.fa-airplay:after,.fad.fa-airplay:after{content:"\e089\e089"}.fa-duotone.fa-fist-raised:after,.fa-duotone.fa-hand-fist:after,.fad.fa-fist-raised:after,.fad.fa-hand-fist:after{content:"\f6de\f6de"}.fa-duotone.fa-shield-quartered:after,.fad.fa-shield-quartered:after{content:"\e575\e575"}.fa-duotone.fa-slash-forward:after,.fad.fa-slash-forward:after{content:"\2f\2f"}.fa-duotone.fa-location-pen:after,.fa-duotone.fa-map-marker-edit:after,.fad.fa-location-pen:after,.fad.fa-map-marker-edit:after{content:"\f607\f607"}.fa-duotone.fa-cloud-moon:after,.fad.fa-cloud-moon:after{content:"\f6c3\f6c3"}.fa-duotone.fa-pot-food:after,.fad.fa-pot-food:after{content:"\e43f\e43f"}.fa-duotone.fa-briefcase:after,.fad.fa-briefcase:after{content:"\f0b1\f0b1"}.fa-duotone.fa-person-falling:after,.fad.fa-person-falling:after{content:"\e546\e546"}.fa-duotone.fa-image-portrait:after,.fa-duotone.fa-portrait:after,.fad.fa-image-portrait:after,.fad.fa-portrait:after{content:"\f3e0\f3e0"}.fa-duotone.fa-user-tag:after,.fad.fa-user-tag:after{content:"\f507\f507"}.fa-duotone.fa-rug:after,.fad.fa-rug:after{content:"\e569\e569"}.fa-duotone.fa-print-slash:after,.fad.fa-print-slash:after{content:"\f686\f686"}.fa-duotone.fa-earth-europe:after,.fa-duotone.fa-globe-europe:after,.fad.fa-earth-europe:after,.fad.fa-globe-europe:after{content:"\f7a2\f7a2"}.fa-duotone.fa-cart-flatbed-suitcase:after,.fa-duotone.fa-luggage-cart:after,.fad.fa-cart-flatbed-suitcase:after,.fad.fa-luggage-cart:after{content:"\f59d\f59d"}.fa-duotone.fa-hand-back-point-ribbon:after,.fad.fa-hand-back-point-ribbon:after{content:"\e1a0\e1a0"}.fa-duotone.fa-rectangle-times:after,.fa-duotone.fa-rectangle-xmark:after,.fa-duotone.fa-times-rectangle:after,.fa-duotone.fa-window-close:after,.fad.fa-rectangle-times:after,.fad.fa-rectangle-xmark:after,.fad.fa-times-rectangle:after,.fad.fa-window-close:after{content:"\f410\f410"}.fa-duotone.fa-tire-rugged:after,.fad.fa-tire-rugged:after{content:"\f634\f634"}.fa-duotone.fa-lightbulb-dollar:after,.fad.fa-lightbulb-dollar:after{content:"\f670\f670"}.fa-duotone.fa-cowbell:after,.fad.fa-cowbell:after{content:"\f8b3\f8b3"}.fa-duotone.fa-baht-sign:after,.fad.fa-baht-sign:after{content:"\e0ac\e0ac"}.fa-duotone.fa-corner:after,.fad.fa-corner:after{content:"\e3fe\e3fe"}.fa-duotone.fa-chevron-double-right:after,.fa-duotone.fa-chevrons-right:after,.fad.fa-chevron-double-right:after,.fad.fa-chevrons-right:after{content:"\f324\f324"}.fa-duotone.fa-book-open:after,.fad.fa-book-open:after{content:"\f518\f518"}.fa-duotone.fa-book-journal-whills:after,.fa-duotone.fa-journal-whills:after,.fad.fa-book-journal-whills:after,.fad.fa-journal-whills:after{content:"\f66a\f66a"}.fa-duotone.fa-inhaler:after,.fad.fa-inhaler:after{content:"\f5f9\f5f9"}.fa-duotone.fa-handcuffs:after,.fad.fa-handcuffs:after{content:"\e4f8\e4f8"}.fa-duotone.fa-snake:after,.fad.fa-snake:after{content:"\f716\f716"}.fa-duotone.fa-exclamation-triangle:after,.fa-duotone.fa-triangle-exclamation:after,.fa-duotone.fa-warning:after,.fad.fa-exclamation-triangle:after,.fad.fa-triangle-exclamation:after,.fad.fa-warning:after{content:"\f071\f071"}.fa-duotone.fa-note-medical:after,.fad.fa-note-medical:after{content:"\e200\e200"}.fa-duotone.fa-database:after,.fad.fa-database:after{content:"\f1c0\f1c0"}.fa-duotone.fa-down-left:after,.fad.fa-down-left:after{content:"\e16a\e16a"}.fa-duotone.fa-arrow-turn-right:after,.fa-duotone.fa-mail-forward:after,.fa-duotone.fa-share:after,.fad.fa-arrow-turn-right:after,.fad.fa-mail-forward:after,.fad.fa-share:after{content:"\f064\f064"}.fa-duotone.fa-face-thinking:after,.fad.fa-face-thinking:after{content:"\e39b\e39b"}.fa-duotone.fa-turn-down-right:after,.fad.fa-turn-down-right:after{content:"\e455\e455"}.fa-duotone.fa-bottle-droplet:after,.fad.fa-bottle-droplet:after{content:"\e4c4\e4c4"}.fa-duotone.fa-mask-face:after,.fad.fa-mask-face:after{content:"\e1d7\e1d7"}.fa-duotone.fa-hill-rockslide:after,.fad.fa-hill-rockslide:after{content:"\e508\e508"}.fa-duotone.fa-scanner-keyboard:after,.fad.fa-scanner-keyboard:after{content:"\f489\f489"}.fa-duotone.fa-circle-o:after,.fad.fa-circle-o:after{content:"\e119\e119"}.fa-duotone.fa-grid-horizontal:after,.fad.fa-grid-horizontal:after{content:"\e307\e307"}.fa-duotone.fa-comment-alt-dollar:after,.fa-duotone.fa-message-dollar:after,.fad.fa-comment-alt-dollar:after,.fad.fa-message-dollar:after{content:"\f650\f650"}.fa-duotone.fa-exchange-alt:after,.fa-duotone.fa-right-left:after,.fad.fa-exchange-alt:after,.fad.fa-right-left:after{content:"\f362\f362"}.fa-duotone.fa-columns-3:after,.fad.fa-columns-3:after{content:"\e361\e361"}.fa-duotone.fa-paper-plane:after,.fad.fa-paper-plane:after{content:"\f1d8\f1d8"}.fa-duotone.fa-road-circle-exclamation:after,.fad.fa-road-circle-exclamation:after{content:"\e565\e565"}.fa-duotone.fa-dungeon:after,.fad.fa-dungeon:after{content:"\f6d9\f6d9"}.fa-duotone.fa-hand-holding-box:after,.fad.fa-hand-holding-box:after{content:"\f47b\f47b"}.fa-duotone.fa-input-text:after,.fad.fa-input-text:after{content:"\e1bf\e1bf"}.fa-duotone.fa-window-alt:after,.fa-duotone.fa-window-flip:after,.fad.fa-window-alt:after,.fad.fa-window-flip:after{content:"\f40f\f40f"}.fa-duotone.fa-align-right:after,.fad.fa-align-right:after{content:"\f038\f038"}.fa-duotone.fa-scanner-gun:after,.fa-duotone.fa-scanner:after,.fad.fa-scanner-gun:after,.fad.fa-scanner:after{content:"\f488\f488"}.fa-duotone.fa-tire:after,.fad.fa-tire:after{content:"\f631\f631"}.fa-duotone.fa-engine:after,.fad.fa-engine:after{content:"\e16e\e16e"}.fa-duotone.fa-money-bill-1-wave:after,.fa-duotone.fa-money-bill-wave-alt:after,.fad.fa-money-bill-1-wave:after,.fad.fa-money-bill-wave-alt:after{content:"\f53b\f53b"}.fa-duotone.fa-life-ring:after,.fad.fa-life-ring:after{content:"\f1cd\f1cd"}.fa-duotone.fa-hands:after,.fa-duotone.fa-sign-language:after,.fa-duotone.fa-signing:after,.fad.fa-hands:after,.fad.fa-sign-language:after,.fad.fa-signing:after{content:"\f2a7\f2a7"}.fa-duotone.fa-caret-circle-right:after,.fa-duotone.fa-circle-caret-right:after,.fad.fa-caret-circle-right:after,.fad.fa-circle-caret-right:after{content:"\f330\f330"}.fa-duotone.fa-wheat:after,.fad.fa-wheat:after{content:"\f72d\f72d"}.fa-duotone.fa-file-spreadsheet:after,.fad.fa-file-spreadsheet:after{content:"\f65b\f65b"}.fa-duotone.fa-audio-description-slash:after,.fad.fa-audio-description-slash:after{content:"\e0a8\e0a8"}.fa-duotone.fa-calendar-day:after,.fad.fa-calendar-day:after{content:"\f783\f783"}.fa-duotone.fa-ladder-water:after,.fa-duotone.fa-swimming-pool:after,.fa-duotone.fa-water-ladder:after,.fad.fa-ladder-water:after,.fad.fa-swimming-pool:after,.fad.fa-water-ladder:after{content:"\f5c5\f5c5"}.fa-duotone.fa-arrows-up-down:after,.fa-duotone.fa-arrows-v:after,.fad.fa-arrows-up-down:after,.fad.fa-arrows-v:after{content:"\f07d\f07d"}.fa-duotone.fa-chess-pawn-alt:after,.fa-duotone.fa-chess-pawn-piece:after,.fad.fa-chess-pawn-alt:after,.fad.fa-chess-pawn-piece:after{content:"\f444\f444"}.fa-duotone.fa-face-grimace:after,.fa-duotone.fa-grimace:after,.fad.fa-face-grimace:after,.fad.fa-grimace:after{content:"\f57f\f57f"}.fa-duotone.fa-wheelchair-alt:after,.fa-duotone.fa-wheelchair-move:after,.fad.fa-wheelchair-alt:after,.fad.fa-wheelchair-move:after{content:"\e2ce\e2ce"}.fa-duotone.fa-level-down-alt:after,.fa-duotone.fa-turn-down:after,.fad.fa-level-down-alt:after,.fad.fa-turn-down:after{content:"\f3be\f3be"}.fa-duotone.fa-square-s:after,.fad.fa-square-s:after{content:"\e27d\e27d"}.fa-duotone.fa-barcode-alt:after,.fa-duotone.fa-rectangle-barcode:after,.fad.fa-barcode-alt:after,.fad.fa-rectangle-barcode:after{content:"\f463\f463"}.fa-duotone.fa-person-walking-arrow-right:after,.fad.fa-person-walking-arrow-right:after{content:"\e552\e552"}.fa-duotone.fa-envelope-square:after,.fa-duotone.fa-square-envelope:after,.fad.fa-envelope-square:after,.fad.fa-square-envelope:after{content:"\f199\f199"}.fa-duotone.fa-dice:after,.fad.fa-dice:after{content:"\f522\f522"}.fa-duotone.fa-unicorn:after,.fad.fa-unicorn:after{content:"\f727\f727"}.fa-duotone.fa-bowling-ball:after,.fad.fa-bowling-ball:after{content:"\f436\f436"}.fa-duotone.fa-pompebled:after,.fad.fa-pompebled:after{content:"\e43d\e43d"}.fa-duotone.fa-brain:after,.fad.fa-brain:after{content:"\f5dc\f5dc"}.fa-duotone.fa-watch-smart:after,.fad.fa-watch-smart:after{content:"\e2cc\e2cc"}.fa-duotone.fa-book-user:after,.fad.fa-book-user:after{content:"\f7e7\f7e7"}.fa-duotone.fa-sensor-cloud:after,.fa-duotone.fa-sensor-smoke:after,.fad.fa-sensor-cloud:after,.fad.fa-sensor-smoke:after{content:"\e02c\e02c"}.fa-duotone.fa-clapperboard-play:after,.fad.fa-clapperboard-play:after{content:"\e132\e132"}.fa-duotone.fa-band-aid:after,.fa-duotone.fa-bandage:after,.fad.fa-band-aid:after,.fad.fa-bandage:after{content:"\f462\f462"}.fa-duotone.fa-calendar-minus:after,.fad.fa-calendar-minus:after{content:"\f272\f272"}.fa-duotone.fa-circle-xmark:after,.fa-duotone.fa-times-circle:after,.fa-duotone.fa-xmark-circle:after,.fad.fa-circle-xmark:after,.fad.fa-times-circle:after,.fad.fa-xmark-circle:after{content:"\f057\f057"}.fa-duotone.fa-circle-4:after,.fad.fa-circle-4:after{content:"\e0f1\e0f1"}.fa-duotone.fa-gifts:after,.fad.fa-gifts:after{content:"\f79c\f79c"}.fa-duotone.fa-album-collection:after,.fad.fa-album-collection:after{content:"\f8a0\f8a0"}.fa-duotone.fa-hotel:after,.fad.fa-hotel:after{content:"\f594\f594"}.fa-duotone.fa-earth-asia:after,.fa-duotone.fa-globe-asia:after,.fad.fa-earth-asia:after,.fad.fa-globe-asia:after{content:"\f57e\f57e"}.fa-duotone.fa-id-card-alt:after,.fa-duotone.fa-id-card-clip:after,.fad.fa-id-card-alt:after,.fad.fa-id-card-clip:after{content:"\f47f\f47f"}.fa-duotone.fa-magnifying-glass-plus:after,.fa-duotone.fa-search-plus:after,.fad.fa-magnifying-glass-plus:after,.fad.fa-search-plus:after{content:"\f00e\f00e"}.fa-duotone.fa-thumbs-up:after,.fad.fa-thumbs-up:after{content:"\f164\f164"}.fa-duotone.fa-cloud-showers:after,.fad.fa-cloud-showers:after{content:"\f73f\f73f"}.fa-duotone.fa-user-clock:after,.fad.fa-user-clock:after{content:"\f4fd\f4fd"}.fa-duotone.fa-onion:after,.fad.fa-onion:after{content:"\e427\e427"}.fa-duotone.fa-clock-twelve-thirty:after,.fad.fa-clock-twelve-thirty:after{content:"\e359\e359"}.fa-duotone.fa-arrow-down-to-dotted-line:after,.fad.fa-arrow-down-to-dotted-line:after{content:"\e095\e095"}.fa-duotone.fa-allergies:after,.fa-duotone.fa-hand-dots:after,.fad.fa-allergies:after,.fad.fa-hand-dots:after{content:"\f461\f461"}.fa-duotone.fa-file-invoice:after,.fad.fa-file-invoice:after{content:"\f570\f570"}.fa-duotone.fa-window-minimize:after,.fad.fa-window-minimize:after{content:"\f2d1\f2d1"}.fa-duotone.fa-rectangle-wide:after,.fad.fa-rectangle-wide:after{content:"\f2fc\f2fc"}.fa-duotone.fa-comment-arrow-up:after,.fad.fa-comment-arrow-up:after{content:"\e144\e144"}.fa-duotone.fa-garlic:after,.fad.fa-garlic:after{content:"\e40e\e40e"}.fa-duotone.fa-coffee:after,.fa-duotone.fa-mug-saucer:after,.fad.fa-coffee:after,.fad.fa-mug-saucer:after{content:"\f0f4\f0f4"}.fa-duotone.fa-brush:after,.fad.fa-brush:after{content:"\f55d\f55d"}.fa-duotone.fa-tree-decorated:after,.fad.fa-tree-decorated:after{content:"\f7dc\f7dc"}.fa-duotone.fa-mask:after,.fad.fa-mask:after{content:"\f6fa\f6fa"}.fa-duotone.fa-calendar-heart:after,.fad.fa-calendar-heart:after{content:"\e0d3\e0d3"}.fa-duotone.fa-magnifying-glass-minus:after,.fa-duotone.fa-search-minus:after,.fad.fa-magnifying-glass-minus:after,.fad.fa-search-minus:after{content:"\f010\f010"}.fa-duotone.fa-flower:after,.fad.fa-flower:after{content:"\f7ff\f7ff"}.fa-duotone.fa-arrow-down-from-arc:after,.fad.fa-arrow-down-from-arc:after{content:"\e614\e614"}.fa-duotone.fa-right-left-large:after,.fad.fa-right-left-large:after{content:"\e5e1\e5e1"}.fa-duotone.fa-ruler-vertical:after,.fad.fa-ruler-vertical:after{content:"\f548\f548"}.fa-duotone.fa-circles-overlap:after,.fad.fa-circles-overlap:after{content:"\e600\e600"}.fa-duotone.fa-user-alt:after,.fa-duotone.fa-user-large:after,.fad.fa-user-alt:after,.fad.fa-user-large:after{content:"\f406\f406"}.fa-duotone.fa-starship-freighter:after,.fad.fa-starship-freighter:after{content:"\e03a\e03a"}.fa-duotone.fa-train-tram:after,.fad.fa-train-tram:after{content:"\e5b4\e5b4"}.fa-duotone.fa-bridge-suspension:after,.fad.fa-bridge-suspension:after{content:"\e4cd\e4cd"}.fa-duotone.fa-trash-check:after,.fad.fa-trash-check:after{content:"\e2af\e2af"}.fa-duotone.fa-user-nurse:after,.fad.fa-user-nurse:after{content:"\f82f\f82f"}.fa-duotone.fa-boombox:after,.fad.fa-boombox:after{content:"\f8a5\f8a5"}.fa-duotone.fa-syringe:after,.fad.fa-syringe:after{content:"\f48e\f48e"}.fa-duotone.fa-cloud-sun:after,.fad.fa-cloud-sun:after{content:"\f6c4\f6c4"}.fa-duotone.fa-shield-exclamation:after,.fad.fa-shield-exclamation:after{content:"\e247\e247"}.fa-duotone.fa-stopwatch-20:after,.fad.fa-stopwatch-20:after{content:"\e06f\e06f"}.fa-duotone.fa-square-full:after,.fad.fa-square-full:after{content:"\f45c\f45c"}.fa-duotone.fa-grip-dots:after,.fad.fa-grip-dots:after{content:"\e410\e410"}.fa-duotone.fa-comment-exclamation:after,.fad.fa-comment-exclamation:after{content:"\f4af\f4af"}.fa-duotone.fa-pen-swirl:after,.fad.fa-pen-swirl:after{content:"\e214\e214"}.fa-duotone.fa-falafel:after,.fad.fa-falafel:after{content:"\e40a\e40a"}.fa-duotone.fa-circle-2:after,.fad.fa-circle-2:after{content:"\e0ef\e0ef"}.fa-duotone.fa-magnet:after,.fad.fa-magnet:after{content:"\f076\f076"}.fa-duotone.fa-jar:after,.fad.fa-jar:after{content:"\e516\e516"}.fa-duotone.fa-gramophone:after,.fad.fa-gramophone:after{content:"\f8bd\f8bd"}.fa-duotone.fa-dice-d12:after,.fad.fa-dice-d12:after{content:"\f6ce\f6ce"}.fa-duotone.fa-note-sticky:after,.fa-duotone.fa-sticky-note:after,.fad.fa-note-sticky:after,.fad.fa-sticky-note:after{content:"\f249\f249"}.fa-duotone.fa-arrow-alt-down:after,.fa-duotone.fa-down:after,.fad.fa-arrow-alt-down:after,.fad.fa-down:after{content:"\f354\f354"}.fa-duotone.fa-100:after,.fa-duotone.fa-hundred-points:after,.fad.fa-100:after,.fad.fa-hundred-points:after{content:"\e41c\e41c"}.fa-duotone.fa-paperclip-vertical:after,.fad.fa-paperclip-vertical:after{content:"\e3c2\e3c2"}.fa-duotone.fa-wind-circle-exclamation:after,.fa-duotone.fa-wind-warning:after,.fad.fa-wind-circle-exclamation:after,.fad.fa-wind-warning:after{content:"\f776\f776"}.fa-duotone.fa-location-pin-slash:after,.fa-duotone.fa-map-marker-slash:after,.fad.fa-location-pin-slash:after,.fad.fa-map-marker-slash:after{content:"\f60c\f60c"}.fa-duotone.fa-face-sad-sweat:after,.fad.fa-face-sad-sweat:after{content:"\e38a\e38a"}.fa-duotone.fa-bug-slash:after,.fad.fa-bug-slash:after{content:"\e490\e490"}.fa-duotone.fa-cupcake:after,.fad.fa-cupcake:after{content:"\e402\e402"}.fa-duotone.fa-light-switch-off:after,.fad.fa-light-switch-off:after{content:"\e018\e018"}.fa-duotone.fa-toggle-large-off:after,.fad.fa-toggle-large-off:after{content:"\e5b0\e5b0"}.fa-duotone.fa-pen-fancy-slash:after,.fad.fa-pen-fancy-slash:after{content:"\e210\e210"}.fa-duotone.fa-truck-container:after,.fad.fa-truck-container:after{content:"\f4dc\f4dc"}.fa-duotone.fa-boot:after,.fad.fa-boot:after{content:"\f782\f782"}.fa-duotone.fa-arrow-up-from-water-pump:after,.fad.fa-arrow-up-from-water-pump:after{content:"\e4b6\e4b6"}.fa-duotone.fa-file-check:after,.fad.fa-file-check:after{content:"\f316\f316"}.fa-duotone.fa-bone:after,.fad.fa-bone:after{content:"\f5d7\f5d7"}.fa-duotone.fa-cards-blank:after,.fad.fa-cards-blank:after{content:"\e4df\e4df"}.fa-duotone.fa-circle-3:after,.fad.fa-circle-3:after{content:"\e0f0\e0f0"}.fa-duotone.fa-bench-tree:after,.fad.fa-bench-tree:after{content:"\e2e7\e2e7"}.fa-duotone.fa-keyboard-brightness-low:after,.fad.fa-keyboard-brightness-low:after{content:"\e1c1\e1c1"}.fa-duotone.fa-ski-boot-ski:after,.fad.fa-ski-boot-ski:after{content:"\e3cd\e3cd"}.fa-duotone.fa-brain-circuit:after,.fad.fa-brain-circuit:after{content:"\e0c6\e0c6"}.fa-duotone.fa-user-injured:after,.fad.fa-user-injured:after{content:"\f728\f728"}.fa-duotone.fa-block-brick-fire:after,.fa-duotone.fa-firewall:after,.fad.fa-block-brick-fire:after,.fad.fa-firewall:after{content:"\e3dc\e3dc"}.fa-duotone.fa-face-sad-tear:after,.fa-duotone.fa-sad-tear:after,.fad.fa-face-sad-tear:after,.fad.fa-sad-tear:after{content:"\f5b4\f5b4"}.fa-duotone.fa-plane:after,.fad.fa-plane:after{content:"\f072\f072"}.fa-duotone.fa-tent-arrows-down:after,.fad.fa-tent-arrows-down:after{content:"\e581\e581"}.fa-duotone.fa-exclamation:after,.fad.fa-exclamation:after{content:"\21\21"}.fa-duotone.fa-arrows-spin:after,.fad.fa-arrows-spin:after{content:"\e4bb\e4bb"}.fa-duotone.fa-face-smile-relaxed:after,.fad.fa-face-smile-relaxed:after{content:"\e392\e392"}.fa-duotone.fa-comment-times:after,.fa-duotone.fa-comment-xmark:after,.fad.fa-comment-times:after,.fad.fa-comment-xmark:after{content:"\f4b5\f4b5"}.fa-duotone.fa-print:after,.fad.fa-print:after{content:"\f02f\f02f"}.fa-duotone.fa-try:after,.fa-duotone.fa-turkish-lira-sign:after,.fa-duotone.fa-turkish-lira:after,.fad.fa-try:after,.fad.fa-turkish-lira-sign:after,.fad.fa-turkish-lira:after{content:"\e2bb\e2bb"}.fa-duotone.fa-face-nose-steam:after,.fad.fa-face-nose-steam:after{content:"\e382\e382"}.fa-duotone.fa-circle-waveform-lines:after,.fa-duotone.fa-waveform-circle:after,.fad.fa-circle-waveform-lines:after,.fad.fa-waveform-circle:after{content:"\e12d\e12d"}.fa-duotone.fa-dollar-sign:after,.fa-duotone.fa-dollar:after,.fa-duotone.fa-usd:after,.fad.fa-dollar-sign:after,.fad.fa-dollar:after,.fad.fa-usd:after{content:"\24\24"}.fa-duotone.fa-ferris-wheel:after,.fad.fa-ferris-wheel:after{content:"\e174\e174"}.fa-duotone.fa-computer-speaker:after,.fad.fa-computer-speaker:after{content:"\f8b2\f8b2"}.fa-duotone.fa-skull-cow:after,.fad.fa-skull-cow:after{content:"\f8de\f8de"}.fa-duotone.fa-x:after,.fad.fa-x:after{content:"\58\58"}.fa-duotone.fa-magnifying-glass-dollar:after,.fa-duotone.fa-search-dollar:after,.fad.fa-magnifying-glass-dollar:after,.fad.fa-search-dollar:after{content:"\f688\f688"}.fa-duotone.fa-users-cog:after,.fa-duotone.fa-users-gear:after,.fad.fa-users-cog:after,.fad.fa-users-gear:after{content:"\f509\f509"}.fa-duotone.fa-person-military-pointing:after,.fad.fa-person-military-pointing:after{content:"\e54a\e54a"}.fa-duotone.fa-bank:after,.fa-duotone.fa-building-columns:after,.fa-duotone.fa-institution:after,.fa-duotone.fa-museum:after,.fa-duotone.fa-university:after,.fad.fa-bank:after,.fad.fa-building-columns:after,.fad.fa-institution:after,.fad.fa-museum:after,.fad.fa-university:after{content:"\f19c\f19c"}.fa-duotone.fa-circle-t:after,.fad.fa-circle-t:after{content:"\e124\e124"}.fa-duotone.fa-sack:after,.fad.fa-sack:after{content:"\f81c\f81c"}.fa-duotone.fa-grid-2:after,.fad.fa-grid-2:after{content:"\e196\e196"}.fa-duotone.fa-camera-cctv:after,.fa-duotone.fa-cctv:after,.fad.fa-camera-cctv:after,.fad.fa-cctv:after{content:"\f8ac\f8ac"}.fa-duotone.fa-umbrella:after,.fad.fa-umbrella:after{content:"\f0e9\f0e9"}.fa-duotone.fa-trowel:after,.fad.fa-trowel:after{content:"\e589\e589"}.fa-duotone.fa-horizontal-rule:after,.fad.fa-horizontal-rule:after{content:"\f86c\f86c"}.fa-duotone.fa-bed-alt:after,.fa-duotone.fa-bed-front:after,.fad.fa-bed-alt:after,.fad.fa-bed-front:after{content:"\f8f7\f8f7"}.fa-duotone.fa-d:after,.fad.fa-d:after{content:"\44\44"}.fa-duotone.fa-stapler:after,.fad.fa-stapler:after{content:"\e5af\e5af"}.fa-duotone.fa-masks-theater:after,.fa-duotone.fa-theater-masks:after,.fad.fa-masks-theater:after,.fad.fa-theater-masks:after{content:"\f630\f630"}.fa-duotone.fa-kip-sign:after,.fad.fa-kip-sign:after{content:"\e1c4\e1c4"}.fa-duotone.fa-face-woozy:after,.fad.fa-face-woozy:after{content:"\e3a2\e3a2"}.fa-duotone.fa-cloud-question:after,.fad.fa-cloud-question:after{content:"\e492\e492"}.fa-duotone.fa-pineapple:after,.fad.fa-pineapple:after{content:"\e31f\e31f"}.fa-duotone.fa-hand-point-left:after,.fad.fa-hand-point-left:after{content:"\f0a5\f0a5"}.fa-duotone.fa-gallery-thumbnails:after,.fad.fa-gallery-thumbnails:after{content:"\e3aa\e3aa"}.fa-duotone.fa-circle-j:after,.fad.fa-circle-j:after{content:"\e112\e112"}.fa-duotone.fa-eyes:after,.fad.fa-eyes:after{content:"\e367\e367"}.fa-duotone.fa-handshake-alt:after,.fa-duotone.fa-handshake-simple:after,.fad.fa-handshake-alt:after,.fad.fa-handshake-simple:after{content:"\f4c6\f4c6"}.fa-duotone.fa-file-caret-up:after,.fa-duotone.fa-page-caret-up:after,.fad.fa-file-caret-up:after,.fad.fa-page-caret-up:after{content:"\e42a\e42a"}.fa-duotone.fa-fighter-jet:after,.fa-duotone.fa-jet-fighter:after,.fad.fa-fighter-jet:after,.fad.fa-jet-fighter:after{content:"\f0fb\f0fb"}.fa-duotone.fa-comet:after,.fad.fa-comet:after{content:"\e003\e003"}.fa-duotone.fa-share-alt-square:after,.fa-duotone.fa-square-share-nodes:after,.fad.fa-share-alt-square:after,.fad.fa-square-share-nodes:after{content:"\f1e1\f1e1"}.fa-duotone.fa-shield-keyhole:after,.fad.fa-shield-keyhole:after{content:"\e248\e248"}.fa-duotone.fa-barcode:after,.fad.fa-barcode:after{content:"\f02a\f02a"}.fa-duotone.fa-plus-minus:after,.fad.fa-plus-minus:after{content:"\e43c\e43c"}.fa-duotone.fa-sliders-v-square:after,.fa-duotone.fa-square-sliders-vertical:after,.fad.fa-sliders-v-square:after,.fad.fa-square-sliders-vertical:after{content:"\f3f2\f3f2"}.fa-duotone.fa-video-camera:after,.fa-duotone.fa-video:after,.fad.fa-video-camera:after,.fad.fa-video:after{content:"\f03d\f03d"}.fa-duotone.fa-comment-middle-alt:after,.fa-duotone.fa-message-middle:after,.fad.fa-comment-middle-alt:after,.fad.fa-message-middle:after{content:"\e1e1\e1e1"}.fa-duotone.fa-graduation-cap:after,.fa-duotone.fa-mortar-board:after,.fad.fa-graduation-cap:after,.fad.fa-mortar-board:after{content:"\f19d\f19d"}.fa-duotone.fa-hand-holding-medical:after,.fad.fa-hand-holding-medical:after{content:"\e05c\e05c"}.fa-duotone.fa-person-circle-check:after,.fad.fa-person-circle-check:after{content:"\e53e\e53e"}.fa-duotone.fa-square-z:after,.fad.fa-square-z:after{content:"\e288\e288"}.fa-duotone.fa-comment-alt-text:after,.fa-duotone.fa-message-text:after,.fad.fa-comment-alt-text:after,.fad.fa-message-text:after{content:"\e1e6\e1e6"}.fa-duotone.fa-level-up-alt:after,.fa-duotone.fa-turn-up:after,.fad.fa-level-up-alt:after,.fad.fa-turn-up:after{content:"\f3bf\f3bf"} :host,:root{--fa-font-light:normal 300 1em/1 "Font Awesome 6 Pro"}@font-face{font-family:"Font Awesome 6 Pro";font-style:normal;font-weight:300;font-display:block;src:url(../webfonts/fa-light-300.woff2) format("woff2"),url(../webfonts/fa-light-300.ttf) format("truetype")}.fa-light,.fal{font-weight:300}:host,:root{--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Pro"}@font-face{font-family:"Font Awesome 6 Pro";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}.fa-regular,.far{font-weight:400}:host,:root{--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Pro"}@font-face{font-family:"Font Awesome 6 Pro";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}:host,:root{--fa-style-family-classic:"Font Awesome 6 Pro";--fa-font-thin:normal 100 1em/1 "Font Awesome 6 Pro"}@font-face{font-family:"Font Awesome 6 Pro";font-style:normal;font-weight:100;font-display:block;src:url(../webfonts/fa-thin-100.woff2) format("woff2"),url(../webfonts/fa-thin-100.ttf) format("truetype")}.fa-thin,.fat{font-weight:100}@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Pro";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Pro";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Pro";font-display:block;font-weight:300;src:url(../webfonts/fa-light-300.woff2) format("woff2"),url(../webfonts/fa-light-300.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Duotone";font-display:block;font-weight:900;src:url(../webfonts/fa-duotone-900.woff2) format("woff2"),url(../webfonts/fa-duotone-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a} +/*! + * Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Commercial License) + * Copyright 2023 Fonticons, Inc. + */ +:host,:root{--fa-style-family-sharp:"Font Awesome 6 Sharp";--fa-font-sharp-light:normal 300 1em/1 "Font Awesome 6 Sharp"}@font-face{font-family:"Font Awesome 6 Sharp";font-style:normal;font-weight:300;font-display:block;src:url(../webfonts/fa-sharp-light-300.woff2) format("woff2"),url(../webfonts/fa-sharp-light-300.ttf) format("truetype")}.fa-light,.fasl{font-weight:300} +/*! + * Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Commercial License) + * Copyright 2023 Fonticons, Inc. + */ +:host,:root{--fa-style-family-sharp:"Font Awesome 6 Sharp";--fa-font-sharp-regular:normal 400 1em/1 "Font Awesome 6 Sharp"}@font-face{font-family:"Font Awesome 6 Sharp";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-sharp-regular-400.woff2) format("woff2"),url(../webfonts/fa-sharp-regular-400.ttf) format("truetype")}.fa-regular,.fasr{font-weight:400} +/*! + * Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Commercial License) + * Copyright 2023 Fonticons, Inc. + */ +:host,:root{--fa-style-family-sharp:"Font Awesome 6 Sharp";--fa-font-sharp-solid:normal 900 1em/1 "Font Awesome 6 Sharp"}@font-face{font-family:"Font Awesome 6 Sharp";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-sharp-solid-900.woff2) format("woff2"),url(../webfonts/fa-sharp-solid-900.ttf) format("truetype")}.fa-solid,.fass{font-weight:900} /*! * bootstrap-fileinput v4.5.2 * http://plugins.krajee.com/file-input @@ -1879,13 +1891,21 @@ video::-webkit-media-text-track-display { outline: none; } -/*! - * Fuel UX v3.1.0 - * Copyright 2012-2014 ExactTarget - * Licensed under the BSD-3-Clause license () - */ +.flatpickr-calendar{background:transparent;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;background:#fff;-webkit-box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08);box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08)}.flatpickr-calendar.open,.flatpickr-calendar.inline{opacity:1;max-height:640px;visibility:visible}.flatpickr-calendar.open{display:inline-block;z-index:99999}.flatpickr-calendar.animate.open{-webkit-animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1);animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1)}.flatpickr-calendar.inline{display:block;position:relative;top:2px}.flatpickr-calendar.static{position:absolute;top:calc(100% + 2px)}.flatpickr-calendar.static.open{z-index:999;display:block}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none !important;box-shadow:none !important}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-calendar .hasWeeks .dayContainer,.flatpickr-calendar .hasTime .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.flatpickr-calendar.hasTime .flatpickr-time{height:40px;border-top:1px solid #e6e6e6}.flatpickr-calendar.noCalendar.hasTime .flatpickr-time{height:auto}.flatpickr-calendar:before,.flatpickr-calendar:after{position:absolute;display:block;pointer-events:none;border:solid transparent;content:'';height:0;width:0;left:22px}.flatpickr-calendar.rightMost:before,.flatpickr-calendar.arrowRight:before,.flatpickr-calendar.rightMost:after,.flatpickr-calendar.arrowRight:after{left:auto;right:22px}.flatpickr-calendar.arrowCenter:before,.flatpickr-calendar.arrowCenter:after{left:50%;right:50%}.flatpickr-calendar:before{border-width:5px;margin:0 -5px}.flatpickr-calendar:after{border-width:4px;margin:0 -4px}.flatpickr-calendar.arrowTop:before,.flatpickr-calendar.arrowTop:after{bottom:100%}.flatpickr-calendar.arrowTop:before{border-bottom-color:#e6e6e6}.flatpickr-calendar.arrowTop:after{border-bottom-color:#fff}.flatpickr-calendar.arrowBottom:before,.flatpickr-calendar.arrowBottom:after{top:100%}.flatpickr-calendar.arrowBottom:before{border-top-color:#e6e6e6}.flatpickr-calendar.arrowBottom:after{border-top-color:#fff}.flatpickr-calendar:focus{outline:0}.flatpickr-wrapper{position:relative;display:inline-block}.flatpickr-months{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flatpickr-months .flatpickr-month{background:transparent;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9);height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.flatpickr-months .flatpickr-prev-month,.flatpickr-months .flatpickr-next-month{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;cursor:pointer;position:absolute;top:0;height:34px;padding:10px;z-index:3;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9)}.flatpickr-months .flatpickr-prev-month.flatpickr-disabled,.flatpickr-months .flatpickr-next-month.flatpickr-disabled{display:none}.flatpickr-months .flatpickr-prev-month i,.flatpickr-months .flatpickr-next-month i{position:relative}.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,.flatpickr-months .flatpickr-next-month.flatpickr-prev-month{/* + /*rtl:begin:ignore*/left:0/* + /*rtl:end:ignore*/}/* + /*rtl:begin:ignore*/ +/* + /*rtl:end:ignore*/ +.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,.flatpickr-months .flatpickr-next-month.flatpickr-next-month{/* + /*rtl:begin:ignore*/right:0/* + /*rtl:end:ignore*/}/* + /*rtl:begin:ignore*/ +/* + /*rtl:end:ignore*/ +.flatpickr-months .flatpickr-prev-month:hover,.flatpickr-months .flatpickr-next-month:hover{color:#959ea9}.flatpickr-months .flatpickr-prev-month:hover svg,.flatpickr-months .flatpickr-next-month:hover svg{fill:#f64747}.flatpickr-months .flatpickr-prev-month svg,.flatpickr-months .flatpickr-next-month svg{width:14px;height:14px}.flatpickr-months .flatpickr-prev-month svg path,.flatpickr-months .flatpickr-next-month svg path{-webkit-transition:fill .1s;transition:fill .1s;fill:inherit}.numInputWrapper{position:relative;height:auto}.numInputWrapper input,.numInputWrapper span{display:inline-block}.numInputWrapper input{width:100%}.numInputWrapper input::-ms-clear{display:none}.numInputWrapper input::-webkit-outer-spin-button,.numInputWrapper input::-webkit-inner-spin-button{margin:0;-webkit-appearance:none}.numInputWrapper span{position:absolute;right:0;width:14px;padding:0 4px 0 2px;height:50%;line-height:50%;opacity:0;cursor:pointer;border:1px solid rgba(57,57,57,0.15);-webkit-box-sizing:border-box;box-sizing:border-box}.numInputWrapper span:hover{background:rgba(0,0,0,0.1)}.numInputWrapper span:active{background:rgba(0,0,0,0.2)}.numInputWrapper span:after{display:block;content:"";position:absolute}.numInputWrapper span.arrowUp{top:0;border-bottom:0}.numInputWrapper span.arrowUp:after{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid rgba(57,57,57,0.6);top:26%}.numInputWrapper span.arrowDown{top:50%}.numInputWrapper span.arrowDown:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(57,57,57,0.6);top:40%}.numInputWrapper span svg{width:inherit;height:auto}.numInputWrapper span svg path{fill:rgba(0,0,0,0.5)}.numInputWrapper:hover{background:rgba(0,0,0,0.05)}.numInputWrapper:hover span{opacity:1}.flatpickr-current-month{font-size:135%;line-height:inherit;font-weight:300;color:inherit;position:absolute;width:75%;left:12.5%;padding:7.48px 0 0 0;line-height:1;height:34px;display:inline-block;text-align:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.flatpickr-current-month span.cur-month{font-family:inherit;font-weight:700;color:inherit;display:inline-block;margin-left:.5ch;padding:0}.flatpickr-current-month span.cur-month:hover{background:rgba(0,0,0,0.05)}.flatpickr-current-month .numInputWrapper{width:6ch;width:7ch\0;display:inline-block}.flatpickr-current-month .numInputWrapper span.arrowUp:after{border-bottom-color:rgba(0,0,0,0.9)}.flatpickr-current-month .numInputWrapper span.arrowDown:after{border-top-color:rgba(0,0,0,0.9)}.flatpickr-current-month input.cur-year{background:transparent;-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;cursor:text;padding:0 0 0 .5ch;margin:0;display:inline-block;font-size:inherit;font-family:inherit;font-weight:300;line-height:inherit;height:auto;border:0;border-radius:0;vertical-align:initial;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-current-month input.cur-year:focus{outline:0}.flatpickr-current-month input.cur-year[disabled],.flatpickr-current-month input.cur-year[disabled]:hover{font-size:100%;color:rgba(0,0,0,0.5);background:transparent;pointer-events:none}.flatpickr-current-month .flatpickr-monthDropdown-months{appearance:menulist;background:transparent;border:none;border-radius:0;box-sizing:border-box;color:inherit;cursor:pointer;font-size:inherit;font-family:inherit;font-weight:300;height:auto;line-height:inherit;margin:-1px 0 0 0;outline:none;padding:0 0 0 .5ch;position:relative;vertical-align:initial;-webkit-box-sizing:border-box;-webkit-appearance:menulist;-moz-appearance:menulist;width:auto}.flatpickr-current-month .flatpickr-monthDropdown-months:focus,.flatpickr-current-month .flatpickr-monthDropdown-months:active{outline:none}.flatpickr-current-month .flatpickr-monthDropdown-months:hover{background:rgba(0,0,0,0.05)}.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background-color:transparent;outline:none;padding:0}.flatpickr-weekdays{background:transparent;text-align:center;overflow:hidden;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:28px}.flatpickr-weekdays .flatpickr-weekdaycontainer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}span.flatpickr-weekday{cursor:default;font-size:90%;background:transparent;color:rgba(0,0,0,0.54);line-height:1;margin:0;text-align:center;display:block;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bolder}.dayContainer,.flatpickr-weeks{padding:1px 0 0 0}.flatpickr-days{position:relative;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;width:307.875px}.flatpickr-days:focus{outline:0}.dayContainer{padding:0;outline:0;text-align:left;width:307.875px;min-width:307.875px;max-width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-wrap:wrap;-ms-flex-pack:justify;-webkit-justify-content:space-around;justify-content:space-around;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.dayContainer + .dayContainer{-webkit-box-shadow:-1px 0 0 #e6e6e6;box-shadow:-1px 0 0 #e6e6e6}.flatpickr-day{background:none;border:1px solid transparent;border-radius:150px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#393939;cursor:pointer;font-weight:400;width:14.2857143%;-webkit-flex-basis:14.2857143%;-ms-flex-preferred-size:14.2857143%;flex-basis:14.2857143%;max-width:39px;height:39px;line-height:39px;margin:0;display:inline-block;position:relative;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.flatpickr-day.inRange,.flatpickr-day.prevMonthDay.inRange,.flatpickr-day.nextMonthDay.inRange,.flatpickr-day.today.inRange,.flatpickr-day.prevMonthDay.today.inRange,.flatpickr-day.nextMonthDay.today.inRange,.flatpickr-day:hover,.flatpickr-day.prevMonthDay:hover,.flatpickr-day.nextMonthDay:hover,.flatpickr-day:focus,.flatpickr-day.prevMonthDay:focus,.flatpickr-day.nextMonthDay:focus{cursor:pointer;outline:0;background:#e6e6e6;border-color:#e6e6e6}.flatpickr-day.today{border-color:#959ea9}.flatpickr-day.today:hover,.flatpickr-day.today:focus{border-color:#959ea9;background:#959ea9;color:#fff}.flatpickr-day.selected,.flatpickr-day.startRange,.flatpickr-day.endRange,.flatpickr-day.selected.inRange,.flatpickr-day.startRange.inRange,.flatpickr-day.endRange.inRange,.flatpickr-day.selected:focus,.flatpickr-day.startRange:focus,.flatpickr-day.endRange:focus,.flatpickr-day.selected:hover,.flatpickr-day.startRange:hover,.flatpickr-day.endRange:hover,.flatpickr-day.selected.prevMonthDay,.flatpickr-day.startRange.prevMonthDay,.flatpickr-day.endRange.prevMonthDay,.flatpickr-day.selected.nextMonthDay,.flatpickr-day.startRange.nextMonthDay,.flatpickr-day.endRange.nextMonthDay{background:#569ff7;-webkit-box-shadow:none;box-shadow:none;color:#fff;border-color:#569ff7}.flatpickr-day.selected.startRange,.flatpickr-day.startRange.startRange,.flatpickr-day.endRange.startRange{border-radius:50px 0 0 50px}.flatpickr-day.selected.endRange,.flatpickr-day.startRange.endRange,.flatpickr-day.endRange.endRange{border-radius:0 50px 50px 0}.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)),.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)),.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)){-webkit-box-shadow:-10px 0 0 #569ff7;box-shadow:-10px 0 0 #569ff7}.flatpickr-day.selected.startRange.endRange,.flatpickr-day.startRange.startRange.endRange,.flatpickr-day.endRange.startRange.endRange{border-radius:50px}.flatpickr-day.inRange{border-radius:0;-webkit-box-shadow:-5px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-5px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover,.flatpickr-day.prevMonthDay,.flatpickr-day.nextMonthDay,.flatpickr-day.notAllowed,.flatpickr-day.notAllowed.prevMonthDay,.flatpickr-day.notAllowed.nextMonthDay{color:rgba(57,57,57,0.3);background:transparent;border-color:transparent;cursor:default}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover{cursor:not-allowed;color:rgba(57,57,57,0.1)}.flatpickr-day.week.selected{border-radius:0;-webkit-box-shadow:-5px 0 0 #569ff7,5px 0 0 #569ff7;box-shadow:-5px 0 0 #569ff7,5px 0 0 #569ff7}.flatpickr-day.hidden{visibility:hidden}.rangeMode .flatpickr-day{margin-top:1px}.flatpickr-weekwrapper{float:left}.flatpickr-weekwrapper .flatpickr-weeks{padding:0 12px;-webkit-box-shadow:1px 0 0 #e6e6e6;box-shadow:1px 0 0 #e6e6e6}.flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%;line-height:28px}.flatpickr-weekwrapper span.flatpickr-day,.flatpickr-weekwrapper span.flatpickr-day:hover{display:block;width:100%;max-width:none;color:rgba(57,57,57,0.3);background:transparent;cursor:default;border:none}.flatpickr-innerContainer{display:block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.flatpickr-rContainer{display:inline-block;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}.flatpickr-time{text-align:center;outline:0;display:block;height:0;line-height:40px;max-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flatpickr-time:after{content:"";display:table;clear:both}.flatpickr-time .numInputWrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:40%;height:40px;float:left}.flatpickr-time .numInputWrapper span.arrowUp:after{border-bottom-color:#393939}.flatpickr-time .numInputWrapper span.arrowDown:after{border-top-color:#393939}.flatpickr-time.hasSeconds .numInputWrapper{width:26%}.flatpickr-time.time24hr .numInputWrapper{width:49%}.flatpickr-time input{background:transparent;-webkit-box-shadow:none;box-shadow:none;border:0;border-radius:0;text-align:center;margin:0;padding:0;height:inherit;line-height:inherit;color:#393939;font-size:14px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-time input.flatpickr-hour{font-weight:bold}.flatpickr-time input.flatpickr-minute,.flatpickr-time input.flatpickr-second{font-weight:400}.flatpickr-time input:focus{outline:0;border:0}.flatpickr-time .flatpickr-time-separator,.flatpickr-time .flatpickr-am-pm{height:inherit;float:left;line-height:inherit;color:#393939;font-weight:bold;width:2%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.flatpickr-time .flatpickr-am-pm{outline:0;width:18%;cursor:pointer;text-align:center;font-weight:400}.flatpickr-time input:hover,.flatpickr-time .flatpickr-am-pm:hover,.flatpickr-time input:focus,.flatpickr-time .flatpickr-am-pm:focus{background:#eee}.flatpickr-input[readonly]{cursor:pointer}@-webkit-keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}} +.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{background-color:transparent;border:none;font-size:1em}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline;list-style:none;padding:0}.select2-container .select2-selection--multiple .select2-selection__clear{background-color:transparent;border:none;font-size:1em}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;margin-left:5px;padding:0;max-width:100%;resize:none;height:18px;vertical-align:bottom;font-family:sans-serif;overflow:hidden;word-break:keep-all}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option--selectable{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;height:26px;margin-right:20px;padding-right:0px}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;padding-bottom:5px;padding-right:5px;position:relative}.select2-container--default .select2-selection--multiple.select2-selection--clearable{padding-right:25px}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;font-weight:bold;height:20px;margin-right:10px;margin-top:5px;position:absolute;right:0;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:inline-block;margin-left:5px;margin-top:5px;padding:0;padding-left:20px;position:relative;max-width:100%;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom;white-space:nowrap}.select2-container--default .select2-selection--multiple .select2-selection__choice__display{cursor:default;padding-left:2px;padding-right:5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{background-color:transparent;border:none;border-right:1px solid #aaa;border-top-left-radius:4px;border-bottom-left-radius:4px;color:#999;cursor:pointer;font-size:1em;font-weight:bold;padding:0 4px;position:absolute;left:0;top:0}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover,.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:focus{background-color:#f1f1f1;color:#333;outline:none}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__display{padding-left:5px;padding-right:2px}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{border-left:1px solid #aaa;border-right:none;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:4px;border-bottom-right-radius:4px}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__clear{float:left;margin-left:10px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--group{padding:0}.select2-container--default .select2-results__option--disabled{color:#999}.select2-container--default .select2-results__option--selected{background-color:#ddd}.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;height:26px;margin-right:20px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0;padding-bottom:5px;padding-right:5px}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;display:inline-block;margin-left:5px;margin-top:5px;padding:0}.select2-container--classic .select2-selection--multiple .select2-selection__choice__display{cursor:default;padding-left:2px;padding-right:5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{background-color:transparent;border:none;border-top-left-radius:4px;border-bottom-left-radius:4px;color:#888;cursor:pointer;font-size:1em;font-weight:bold;padding:0 4px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555;outline:none}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__display{padding-left:5px;padding-right:2px}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:4px;border-bottom-right-radius:4px}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option--group{padding:0}.select2-container--classic .select2-results__option--disabled{color:grey}.select2-container--classic .select2-results__option--highlighted.select2-results__option--selectable{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} -@charset "UTF-8";.fuelux .clearfix{*zoom:1}.fuelux .clearfix:before,.fuelux .clearfix:after{display:table;content:"";line-height:0}.fuelux .clearfix:after{clear:both}@font-face{font-family:fuelux;src:url(https://groups.io/fonts/fuelux.eot);src:url(https://groups.io/fonts/fuelux.eot?) format("embedded-opentype"),url(https://groups.io/fonts/fuelux.woff) format("woff"),url(https://groups.io/fonts/fuelux.ttf) format("truetype"),url(https://groups.io/fonts/fuelux.svg) format("svg");font-weight:400;font-style:normal}.fuelux [class^=fueluxicon-]:before,.fuelux [class*=" fueluxicon-"]:before{font-family:fuelux!important;font-style:normal!important;font-weight:400!important;font-variant:normal!important;text-transform:none!important;line-height:1;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fuelux .fueluxicon-loader-full:before{content:"\e000"}.fuelux .fueluxicon-loader-1:before{content:"\e001"}.fuelux .fueluxicon-loader-2:before{content:"\e002"}.fuelux .fueluxicon-loader-3:before{content:"\e003"}.fuelux .fueluxicon-loader-4:before{content:"\e004"}.fuelux .fueluxicon-loader-5:before{content:"\e005"}.fuelux .fueluxicon-loader-6:before{content:"\e006"}.fuelux .fueluxicon-loader-7:before{content:"\e007"}.fuelux .fueluxicon-loader-8:before{content:"\e008"}.fuelux .fueluxicon-bullet:before{content:"\e009"}.fuelux .checkbox.highlight{padding:4px}.fuelux .checkbox.highlight.checked{background:#e9e9e9;border-radius:4px}.fuelux .checkbox input[type=checkbox]:focus+.checkbox-label,.fuelux .checkbox input[type=checkbox]:hover+.checkbox-label,.fuelux .checkbox .checkbox-label:hover{color:#999}.fuelux .form-horizontal .checkbox-inline{padding-top:0}.fuelux .input-group-addon.checkbox-custom.checkbox-inline:before{left:11px;top:9px}.fuelux .checkbox-custom{position:relative}.fuelux .checkbox-custom:before{font-family:"Glyphicons Halflings"!important;font-style:normal!important;font-weight:400!important;font-variant:normal!important;text-transform:none!important;line-height:1;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;border:1px solid #adadad;border-radius:4px;color:#fff;content:" ";font-size:9px;height:14px;left:0;padding:1px 0 0 1px;position:absolute;top:3px;width:14px}.fuelux .checkbox-custom.checked:before{background:#39b3d7;border-color:#39b3d7;content:"\e013"}.fuelux .checkbox-custom.disabled{cursor:not-allowed}.fuelux .checkbox-custom.disabled:before{cursor:not-allowed;opacity:.5}.fuelux .checkbox-custom.checkbox-inline:before{left:0;top:3px}.fuelux .checkbox-custom.checkbox-inline.highlight{padding:4px 4px 4px 24px}.fuelux .checkbox-custom.checkbox-inline.highlight:before{left:4px;top:7px}.fuelux .checkbox-custom.checkbox-inline.highlight.checked{background:#e9e9e9;border-radius:4px}.fuelux .checkbox-custom input[type=checkbox]:focus+.checkbox-label{color:#999}.fuelux .combobox.disabled .input-group-btn{cursor:not-allowed}.fuelux .datepicker-calendar{padding:16px 16px 0;min-height:262px}.fuelux .datepicker-calendar button{border:0;padding:0;background-color:transparent}.fuelux .datepicker-calendar-days{height:182px;margin:10px 0 12px;width:100%}.fuelux .datepicker-calendar-days thead{border-bottom:1px solid #cccaca}.fuelux .datepicker-calendar-days tbody:before{line-height:3px;content:"\200C";display:block}.fuelux .datepicker-calendar-days td,.fuelux .datepicker-calendar-days th{font-size:14px;height:32px;text-align:center;vertical-align:middle;width:14.29%}.fuelux .datepicker-calendar-days td b,.fuelux .datepicker-calendar-days td button{color:#231f20;display:inline-block;font-weight:400;height:30px;text-decoration:none;width:30px}.fuelux .datepicker-calendar-days td b{line-height:30px}.fuelux .datepicker-calendar-days td span{display:block}.fuelux .datepicker-calendar-days td span:hover{background:#b7e3f8;text-decoration:none}.fuelux .datepicker-calendar-days td.current-day b,.fuelux .datepicker-calendar-days td.current-day button{border:1px solid #1d75bb}.fuelux .datepicker-calendar-days td.last-month,.fuelux .datepicker-calendar-days td.next-month{background:#e3e2e1}.fuelux .datepicker-calendar-days td.past b,.fuelux .datepicker-calendar-days td.past button{color:#8d8787}.fuelux .datepicker-calendar-days td.restricted b,.fuelux .datepicker-calendar-days td.restricted button{cursor:no-drop;position:relative}.fuelux .datepicker-calendar-days td.restricted b:before,.fuelux .datepicker-calendar-days td.restricted button:before{border-top:1px solid #a94442;bottom:0;content:" ";display:block;left:5px;position:absolute;right:5px;top:50%}.fuelux .datepicker-calendar-days td.restricted b:hover,.fuelux .datepicker-calendar-days td.restricted button:hover{background:0 0}.fuelux .datepicker-calendar-days td.selected span{background:#1d75bb}.fuelux .datepicker-calendar-days td.selected span:hover{background:#0f5f9f}.fuelux .datepicker-calendar-days td.selected b,.fuelux .datepicker-calendar-days td.selected button{color:#fff}.fuelux .datepicker-calendar-days td.selected.current-day{box-shadow:0 0 0 1px #fff offset}.fuelux .datepicker-calendar-days td.selected.current-day span:hover b,.fuelux .datepicker-calendar-days td.selected.current-day span:hover button{border-color:#0f5f9f}.fuelux .datepicker-calendar-days th{font-weight:700;height:22px;vertical-align:top}.fuelux .datepicker-calendar-header{*zoom:1}.fuelux .datepicker-calendar-header:before,.fuelux .datepicker-calendar-header:after{display:table;content:"";line-height:0}.fuelux .datepicker-calendar-header:after{clear:both}.fuelux .datepicker-calendar-header button{border:0;padding:0;background-color:transparent}.fuelux .datepicker-calendar-header .title{margin:0 auto;text-align:center;display:block;width:174px;color:#4d4d4f;font-size:20px;line-height:30px;text-decoration:underline;vertical-align:middle}.fuelux .datepicker-calendar-header .title:hover{color:#1d75bb;text-decoration:underline}.fuelux .datepicker-calendar-header .title.disabled{cursor:default;pointer-events:none;text-decoration:none}.fuelux .datepicker-calendar-header .title .month{display:inline;margin:0;padding:0}.fuelux .datepicker-calendar-header .title .month span{display:none}.fuelux .datepicker-calendar-header .title .month span.current{display:inline}.fuelux .datepicker-calendar-header .next,.fuelux .datepicker-calendar-header .prev{background:#666669;background-clip:padding-box;border-radius:30px;cursor:pointer;float:left;height:30px;text-align:center;width:30px}.fuelux .datepicker-calendar-header .next span.glyphicon,.fuelux .datepicker-calendar-header .prev span.glyphicon{color:#fff;font-size:16px;line-height:30px}.fuelux .datepicker-calendar-header .next:hover,.fuelux .datepicker-calendar-header .prev:hover{background:#1d75bb}.fuelux .datepicker-calendar-header .next{float:right}.fuelux .datepicker-calendar-header .next span.glyphicon{line-height:28px}.fuelux .datepicker-calendar-footer{background:#e3e2e1;background-clip:padding-box;border-radius:0 0 4px 4px;border-top:1px solid #cccaca;height:30px;margin:0 -16px;padding:4px 14px}.fuelux .datepicker-calendar-footer .datepicker-today{color:#231f20;font-size:14px;text-decoration:underline}.fuelux .datepicker-calendar-footer .datepicker-today:hover{color:#1b75bb;text-decoration:underline}.fuelux .datepicker-calendar-footer .datepicker-today.disabled{color:#8b8c8e;cursor:default;pointer-events:none}.fuelux .datepicker-calendar-footer .datepicker-today.disabled:hover{color:#8b8c8e}.fuelux .datepicker-calendar-wrapper{border:1px solid #6e6f71;min-height:20px;padding:0;width:300px}.fuelux .datepicker-wheels{display:none}.fuelux .datepicker-wheels ul button{border:0;padding:0;background-color:transparent}.fuelux .datepicker-wheels-footer{background:#e3e2e1;border-radius:0 0 4px 4px;border-top:1px solid #cccaca;clear:both}.fuelux .datepicker-wheels-footer .datepicker-wheels-back{display:block;color:#4d4d4f;float:left;line-height:22px;border:0;background-color:transparent}.fuelux .datepicker-wheels-footer .datepicker-wheels-back:hover{color:#1d75bb}.fuelux .datepicker-wheels-footer .datepicker-wheels-select{float:right;background-color:transparent;color:#049cdb}.fuelux .datepicker-wheels-footer .datepicker-wheels-select:hover{color:#1d75bb}.fuelux .datepicker-wheels-month,.fuelux .datepicker-wheels-year{float:left;width:50%}.fuelux .datepicker-wheels-month ul,.fuelux .datepicker-wheels-year ul{height:217px;list-style-type:none;margin:0;overflow:auto;padding:0;text-align:center}.fuelux .datepicker-wheels-month ul li,.fuelux .datepicker-wheels-year ul li{margin:4px 0}.fuelux .datepicker-wheels-month ul li button,.fuelux .datepicker-wheels-year ul li button{width:100%;text-align:center;color:#414041;display:block;font-size:16px;line-height:24px;text-decoration:none}.fuelux .datepicker-wheels-month ul li button:hover,.fuelux .datepicker-wheels-year ul li button:hover{background:#aee0f8;text-decoration:none}.fuelux .datepicker-wheels-month ul li.selected button,.fuelux .datepicker-wheels-year ul li.selected button{background:#1d75bb;color:#fff}.fuelux .datepicker-wheels-month ul li.selected button:hover,.fuelux .datepicker-wheels-year ul li.selected button:hover{background:#0f5f9f}.fuelux .datepicker-wheels-month .header,.fuelux .datepicker-wheels-year .header{background:#e3e2e1;background-clip:padding-box;border-bottom:1px solid #cccaca;border-radius:4px 0 0;color:#4d4d4f;font-size:20px;font-weight:700;line-height:30px;margin-top:0;margin-bottom:0;text-align:center}.fuelux .datepicker-wheels-month.full,.fuelux .datepicker-wheels-year.full{border-left:0;width:100%}.fuelux .datepicker-wheels-month.full .header,.fuelux .datepicker-wheels-year.full .header{border-radius:4px 4px 0 0}.fuelux .datepicker-wheels-year{border-left:1px solid #cccaca;float:right}.fuelux .datepicker-wheels-year .header{border-radius:0 4px 0 0}.fuelux .infinitescroll{overflow-y:auto}.fuelux .infinitescroll .infinitescroll-end{clear:both;font-style:italic;padding:6px;text-align:center}.fuelux .infinitescroll .infinitescroll-load{clear:both;padding:6px}.fuelux .infinitescroll .infinitescroll-load button{padding:5px 12px;width:100%}.fuelux .infinitescroll .infinitescroll-load .loader{font-size:32px;height:32px;margin:0 auto;width:32px}.fuelux .dropUp{-webkit-box-shadow:0 0 10px rgba(0,0,0,.2);-moz-box-shadow:0 0 10px rgba(0,0,0,.2);box-shadow:0 0 10px rgba(0,0,0,.2)}.fuelux .loader{height:64px;font-size:64px;position:relative;width:64px}.fuelux .loader:after,.fuelux .loader:before{font-family:fuelux!important;font-style:normal!important;font-weight:400!important;font-variant:normal!important;text-transform:none!important;line-height:1;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;bottom:0;display:block;left:0;position:absolute;right:0;top:0}.fuelux .loader:before{content:'\e000';opacity:.33}.fuelux .loader.iefix:before{color:#bcbcbc;opacity:1}.fuelux .loader[data-frame="1"]:after{content:'\e001'}.fuelux .loader[data-frame="2"]:after{content:'\e002'}.fuelux .loader[data-frame="3"]:after{content:'\e003'}.fuelux .loader[data-frame="4"]:after{content:'\e004'}.fuelux .loader[data-frame="5"]:after{content:'\e005'}.fuelux .loader[data-frame="6"]:after{content:'\e006'}.fuelux .loader[data-frame="7"]:after{content:'\e007'}.fuelux .loader[data-frame="8"]:after{content:'\e008'}.fuelux input.glass,.fuelux textarea.glass{background:0 0;border:1px solid #fff;box-shadow:none}.fuelux input.glass:hover,.fuelux textarea.glass:hover{background:#d9edf7;border-color:#66afe9;cursor:pointer}.fuelux input.glass:hover[disabled],.fuelux textarea.glass:hover[disabled]{background:0 0;border-color:#fff;cursor:not-allowed}.fuelux input.glass:focus,.fuelux textarea.glass:focus{background:#fff;border-color:#66afe9;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);cursor:auto}.fuelux input.glass:focus[disabled],.fuelux textarea.glass:focus[disabled]{background:0 0;border-color:#fff;cursor:not-allowed}.fuelux input.glass[disabled],.fuelux textarea.glass[disabled]{cursor:not-allowed}.fuelux .input-group-addon{padding:6px 18px}.fuelux [data-toggle=buttons]>.btn>input[type=radio],.fuelux [data-toggle=buttons]>.btn>input[type=checkbox]{display:inline;position:absolute;left:-9999px}.fuelux .pillbox{border:1px solid #BBB;border-radius:4px;cursor:text;padding:3px}.fuelux .pillbox[data-readonly]{border:1px solid transparent}.fuelux .pillbox[data-readonly].truncate .pillbox-input-wrap{display:inline-block}.fuelux .pillbox[data-readonly].truncate .pillbox-input-wrap.truncated{display:none}.fuelux .pillbox[data-readonly].truncate .pillbox-more{display:inline}.fuelux .pillbox[data-readonly] .pill span.glyphicon-close{display:none}.fuelux .pillbox[data-readonly] .pillbox-add-item{display:none}.fuelux .pillbox[data-readonly] .pillbox-input-wrap{display:none}.fuelux .pillbox[data-readonly] .pillbox-input-wrap button.dropdown-toggle{display:none}.fuelux .pillbox.pills-editable .pill-group .pill span{cursor:text}.fuelux .pillbox.pills-editable .pill-group .pill span.glyphicon-close{cursor:pointer}.fuelux .pillbox>.pill-group{margin:0;padding:0;width:100%}.fuelux .pillbox>.pill-group>.pill{margin:2px;cursor:default;float:left;word-break:break-all}.fuelux .pillbox>.pill-group>.pill.pillbox-highlight{outline:1px dotted #999}.fuelux .pillbox>.pill-group>.pill.truncated{display:none}.fuelux .pillbox>.pill-group>.pill .pillbox-list-edit{border:0;color:#333;font-weight:400;border-radius:2px}.fuelux .pillbox>.pill-group>.pill .pillbox-list-edit:focus{outline:0;border:0}.fuelux .pillbox>.pill-group>.pill .glyphicon-close{cursor:pointer;top:-1px;left:2px}.fuelux .pillbox>.pill-group>.pill .glyphicon-close:before{content:" \00d7"}.fuelux .pillbox>.pill-group>.pill .glyphicon-close:hover{opacity:.4}.fuelux .pillbox .pillbox-input-wrap{position:relative;margin:4px 0 3px 3px;float:left}.fuelux .pillbox .pillbox-input-wrap.editing{border:1px solid #ccc;border-radius:4px;margin:2px 0 3px 3px}.fuelux .pillbox .pillbox-input-wrap.editing input.pillbox-add-item{border-radius:4px;color:#333;height:32px}.fuelux .pillbox .pillbox-add-item{border:0;box-shadow:none}.fuelux .pillbox .pillbox-add-item:focus{outline:0;border:0}.fuelux .pillbox .pillbox-more{cursor:pointer;display:none;line-height:30px}.fuelux .pillbox .suggest{max-height:166px;overflow-y:auto}.fuelux .pillbox .suggest>li{white-space:nowrap;cursor:pointer;padding:3px 20px}.fuelux .pillbox .suggest>li.pillbox-suggest-sel{background-color:#eee}.fuelux .pillbox .suggest>li:hover{background-color:#eee}.fuelux .placard{display:inline-block;position:relative}.fuelux .placard[data-ellipsis=true].showing input.placard-field{overflow:visible;text-overflow:clip;white-space:normal}.fuelux .placard[data-ellipsis=true] input.placard-field{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fuelux .placard[data-ellipsis=true] textarea.placard-field[readonly]{overflow:hidden}.fuelux .placard.showing .placard-footer,.fuelux .placard.showing .placard-header,.fuelux .placard.showing .placard-popup{display:block;z-index:1}.fuelux .placard.showing input.placard-field,.fuelux .placard.showing textarea.placard-field{background:#fff;border:1px solid #CCC;box-shadow:none;position:relative;z-index:1}.fuelux .placard input.placard-field,.fuelux .placard textarea.placard-field{resize:none}.fuelux .placard input.placard-field[readonly],.fuelux .placard textarea.placard-field[readonly]{background:#fff;cursor:auto}.fuelux .placard input.placard-field[readonly].glass,.fuelux .placard textarea.placard-field[readonly].glass{background:0 0}.fuelux .placard input.placard-field[readonly].glass:hover,.fuelux .placard textarea.placard-field[readonly].glass:hover{background:#d9edf7;cursor:pointer}.fuelux .placard input.placard-field:focus,.fuelux .placard textarea.placard-field:focus{border:1px solid #CCC;box-shadow:none}.fuelux .placard-cancel{font-size:12px;margin-right:4px;vertical-align:middle}.fuelux .placard-footer,.fuelux .placard-header{display:none;left:0;line-height:1;position:absolute;right:0}.fuelux .placard-footer{padding:4px 0 8px;text-align:right;top:100%}.fuelux .placard-header{bottom:100%;padding:8px 0 4px}.fuelux .placard-header h1,.fuelux .placard-header h2,.fuelux .placard-header h3,.fuelux .placard-header h4,.fuelux .placard-header h5,.fuelux .placard-header h6{margin:0}.fuelux .placard-popup{background:#d9edf7;background-clip:padding-box;border:1px solid #ccc;border-radius:4px;bottom:-8px;box-shadow:0 0 0 1px #fff inset;display:none;left:-8px;position:absolute;right:-8px;top:-8px}.fuelux .radio.highlight{padding:4px}.fuelux .radio.highlight.checked{background:#e9e9e9;border-radius:4px}.fuelux .radio input[type=radio]:focus+.radio-label,.fuelux .radio input[type=radio]:hover+.radio-label,.fuelux .radio .radio-label:hover{color:#999}.fuelux .form-horizontal .radio-inline{padding-top:0}.fuelux .input-group-addon.radio-custom.radio-inline:before{left:11px;top:9px}.fuelux .radio-custom{position:relative}.fuelux .radio-custom:after{background:0 0;border-radius:6px;content:" ";height:6px;left:4px;position:absolute;top:7px;width:6px}.fuelux .radio-custom:before{border:1px solid #adadad;border-radius:14px;content:" ";height:14px;left:0;position:absolute;top:3px;width:14px}.fuelux .radio-custom.checked:after{background:#fff}.fuelux .radio-custom.checked:before{background:#39b3d7;border-color:#39b3d7}.fuelux .radio-custom.disabled{cursor:not-allowed}.fuelux .radio-custom.disabled:after{cursor:not-allowed}.fuelux .radio-custom.disabled:before{cursor:not-allowed;opacity:.5}.fuelux .radio-custom.radio-inline:after{left:4px;top:7px}.fuelux .radio-custom.radio-inline:before{left:0;top:3px}.fuelux .radio-custom.radio-inline.highlight{padding:4px 4px 4px 24px}.fuelux .radio-custom.radio-inline.highlight:after{left:8px;top:11px}.fuelux .radio-custom.radio-inline.highlight:before{left:4px;top:7px}.fuelux .radio-custom.radio-inline.highlight.checked{background:#e9e9e9;border-radius:4px}.fuelux .radio-custom input[type=radio]:focus+.radio-label{color:#999}.fuelux .repeater{border:1px solid #ddd;border-radius:4px}.fuelux .repeater-canvas.scrolling{bottom:0;left:0;overflow-y:auto;position:absolute;right:0;top:0}.fuelux .repeater-header,.fuelux .repeater-footer{background:#f9f9f9;min-height:50px;padding:8px;*zoom:1}.fuelux .repeater-header:before,.fuelux .repeater-footer:before,.fuelux .repeater-header:after,.fuelux .repeater-footer:after{display:table;content:"";line-height:0}.fuelux .repeater-header:after,.fuelux .repeater-footer:after{clear:both}.fuelux .repeater-header-left,.fuelux .repeater-footer-left{float:left}.fuelux .repeater-header-right,.fuelux .repeater-footer-right{float:right}@media (max-width:625px){.fuelux .repeater-header-left,.fuelux .repeater-footer-left,.fuelux .repeater-header-right,.fuelux .repeater-footer-right{float:none;*zoom:1}.fuelux .repeater-header-left:before,.fuelux .repeater-footer-left:before,.fuelux .repeater-header-right:before,.fuelux .repeater-footer-right:before,.fuelux .repeater-header-left:after,.fuelux .repeater-footer-left:after,.fuelux .repeater-header-right:after,.fuelux .repeater-footer-right:after{display:table;content:"";line-height:0}.fuelux .repeater-header-left:after,.fuelux .repeater-footer-left:after,.fuelux .repeater-header-right:after,.fuelux .repeater-footer-right:after{clear:both}.fuelux .repeater-header-left,.fuelux .repeater-footer-left{margin-bottom:8px}}.fuelux .repeater-header{border-bottom:1px solid #ddd;border-top-right-radius:4px;border-top-left-radius:4px}.fuelux .repeater-footer{border-top:1px solid #ddd;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.fuelux .repeater-loader{display:none;left:50%;position:absolute;margin:-32px 0 0 -32px;top:50%}.fuelux .repeater-viewport{min-height:80px;position:relative}.fuelux .repeater-pagination label{font-weight:400}.fuelux .repeater-pagination .repeater-primaryPaging{display:none;vertical-align:middle;width:116px}.fuelux .repeater-pagination .repeater-primaryPaging.active{display:inline-block}.fuelux .repeater-pagination .repeater-primaryPaging ul.dropdown-menu{min-width:116px}.fuelux .repeater-pagination .repeater-secondaryPaging{display:none;width:82px}.fuelux .repeater-pagination .repeater-secondaryPaging.active{display:inline-block}.fuelux .repeater-search{float:left;width:200px}.fuelux .repeater-title{display:block;float:left;line-height:34px;margin-right:10px}.fuelux .repeater[data-currentview=list] .repeater-canvas.scrolling{overflow:visible}.fuelux .repeater[data-currentview=list] .repeater-canvas.scrolling .repeater-list{bottom:0;left:0;position:absolute;right:0;top:0}.fuelux .repeater[data-currentview=list] .repeater-canvas.scrolling .repeater-list-wrapper{height:100%;overflow:auto}.fuelux .repeater[data-currentview=list] .repeater-loader{margin-top:-12px}.fuelux .repeater[data-currentview=list] .repeater-loader.noHeader{margin-top:-32px}.fuelux .repeater[data-currentview=list] .repeater-viewport{overflow:hidden}.fuelux .repeater-list{position:relative}.fuelux .repeater-list table{margin-bottom:0;width:100%}.fuelux .repeater-list table tbody td{border-bottom:1px solid #ddd;border-left:1px solid #ddd;border-top:0}.fuelux .repeater-list table tbody td:first-child{border-left:0}.fuelux .repeater-list table tbody tr.empty td{border-bottom:0;font-style:italic;padding:20px;text-align:center;width:100%}.fuelux .repeater-list table tbody tr.selectable:hover{background:#d9edf7;cursor:pointer}.fuelux .repeater-list table tbody tr.selected{background:#66AFE9;color:#fff}.fuelux .repeater-list table tbody tr.selected:hover{background:#428bca}.fuelux .repeater-list table tbody tr.selected td:first-child{padding-left:30px}.fuelux .repeater-list table thead>tr>th{background:0 0;border-bottom:1px solid transparent;border-left:1px solid transparent;border-top:0;color:rgba(0,0,0,0);line-height:1.42857;padding:8px}.fuelux .repeater-list table thead>tr>th:first-child{border-left:0}.fuelux .repeater-list table thead>tr>th.sorted span.glyphicon{display:block;visibility:hidden}.fuelux .repeater-list table thead>tr>th span.glyphicon{display:none;float:right;margin-top:2px}.fuelux .repeater-list-check{display:inline-block;height:0;line-height:0;position:relative;vertical-align:top;width:0}.fuelux .repeater-list-check span.glyphicon{left:-22px;position:absolute;top:2px}.fuelux .repeater-list-heading{background:#F9F9F9;border-bottom:1px solid #ddd;border-left:1px solid #ddd;border-top:0;color:#333;line-height:1.42857;margin-left:-9px;padding:8px;position:absolute;top:0;z-index:1}.fuelux .repeater-list-heading.shifted{margin-left:-1px}@media screen and (-webkit-min-device-pixel-ratio:0){.fuelux .repeater-list-heading.shifted{margin-left:0}}.fuelux .repeater-list-heading.sortable:hover,.fuelux .repeater-list-heading.sortable.sorted{background:#F1F1F1;cursor:pointer;background-color:#f1f1f1;background-image:-moz-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f9f9f9),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:-o-linear-gradient(top,#f9f9f9,#e5e5e5);background-image:linear-gradient(to bottom,#f9f9f9,#e5e5e5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#ffe5e5e5', GradientType=0)}.fuelux .repeater-list-heading.sortable.sorted span.glyphicon{display:block;visibility:visible}.fuelux .repeater-list-heading span.glyphicon{display:none;float:right;margin-top:2px}.fuelux .repeater-thumbnail{border:1px solid #ddd;color:#666;float:left;min-height:110px;min-width:100px;margin:8px 7px;text-align:center}.fuelux .repeater-thumbnail.selectable:hover{background:#d9edf7;cursor:pointer}.fuelux .repeater-thumbnail.selected{background:#66AFE9;color:#fff}.fuelux .repeater-thumbnail.selected:hover{background:#428bca}.fuelux .repeater-thumbnail img{display:block;margin-top:10px;margin-bottom:3px}.fuelux .repeater-thumbnail-cont{height:100%;overflow-y:auto;padding:6px;width:100%}.fuelux .repeater-thumbnail-cont div.empty{font-style:italic;padding:20px 10px;text-align:center}.fuelux .spinbox{display:inline-block;position:relative}.fuelux .spinbox.digits-3{width:60px}.fuelux .spinbox.disabled .spinbox-buttons{cursor:not-allowed}.fuelux .spinbox .spinbox-input{float:left;padding-bottom:3px;padding:0 25px 0 7px}.fuelux .spinbox .btn{position:relative;width:20px;height:13px;padding-top:0;padding-right:9px;padding-left:9px}.fuelux .spinbox .btn.disabled{cursor:not-allowed}.fuelux .spinbox .spinbox-buttons{position:absolute;height:28px;width:20px;right:2px}.fuelux .spinbox .spinbox-up{padding:0 0 14px 1px;top:2px}.fuelux .spinbox .spinbox-up .glyphicon-chevron-up{position:relative;top:0}.fuelux .spinbox .btn-group>.btn.spinbox-up{border-top-right-radius:4px}.fuelux .spinbox .spinbox-down{padding:0 0 8px 1px;top:2px;height:15px;border-bottom-left-radius:4px}.fuelux .spinbox .spinbox-down .glyphicon-chevron-down{position:relative;left:-1px;top:0}.fuelux .scheduler .control-label{min-width:7em}.fuelux .scheduler .inline-form-text{float:left;line-height:27px;margin-top:4px}.fuelux .scheduler .start-datetime.form-group{margin-bottom:0}.fuelux .scheduler .start-datetime .form-group{margin-left:0}.fuelux .scheduler .start-datetime .combobox{max-width:9em}.fuelux .scheduler .start-datetime .combobox .dropdown-menu{max-height:200px;overflow:auto}.fuelux .scheduler .start-datetime .dropdown{float:left;margin:0 10px 0 0}.fuelux .scheduler .timezone-container .input-group{max-width:20em}.fuelux .scheduler .timezone-container .dropdown-label{height:18px;white-space:nowrap;max-width:20em;overflow:hidden;text-overflow:ellipsis}.fuelux .scheduler .timezone-container .dropdown-menu{max-height:200px;overflow:auto}.fuelux .scheduler .repeat-panel{margin-left:0}.fuelux .scheduler .repeat-panel label{font-weight:400}.fuelux .scheduler .repeat-panel .radio{margin-right:10px}.fuelux .scheduler .repeat-panel .form-group{margin-left:0}.fuelux .scheduler .repeat-interval{margin-left:0;*zoom:1}.fuelux .scheduler .repeat-interval:before,.fuelux .scheduler .repeat-interval:after{display:table;content:"";line-height:0}.fuelux .scheduler .repeat-interval:after{clear:both}.fuelux .scheduler .repeat-interval .form-group{margin-left:0}.fuelux .scheduler .repeat-interval .dropdown-menu{max-height:200px;overflow:auto}.fuelux .scheduler .repeat-interval .repeat-every-panel{float:left}.fuelux .scheduler .repeat-interval .repeat-every-panel .repeat-every-pretext{padding:0 10px}.fuelux .scheduler .repeat-interval .repeat-every-panel .spinbox{float:left;margin-right:10px}.fuelux .scheduler .repeat-interval .repeat-every-panel .spinbox input{margin-bottom:0}.fuelux .scheduler .repeat-monthly .repeat-monthly-date{margin-top:10px;*zoom:1}.fuelux .scheduler .repeat-monthly .repeat-monthly-date:before,.fuelux .scheduler .repeat-monthly .repeat-monthly-date:after{display:table;content:"";line-height:0}.fuelux .scheduler .repeat-monthly .repeat-monthly-date:after{clear:both}.fuelux .scheduler .repeat-monthly .repeat-monthly-date .selectlist{margin-left:5px}.fuelux .scheduler .repeat-monthly .repeat-monthly-day{margin-top:10px;*zoom:1}.fuelux .scheduler .repeat-monthly .repeat-monthly-day:before,.fuelux .scheduler .repeat-monthly .repeat-monthly-day:after{display:table;content:"";line-height:0}.fuelux .scheduler .repeat-monthly .repeat-monthly-day:after{clear:both}.fuelux .scheduler .repeat-monthly .month-days{margin-left:10px}.fuelux .scheduler .repeat-yearly .repeat-yearly-date{margin-top:10px;*zoom:1}.fuelux .scheduler .repeat-yearly .repeat-yearly-date:before,.fuelux .scheduler .repeat-yearly .repeat-yearly-date:after{display:table;content:"";line-height:0}.fuelux .scheduler .repeat-yearly .repeat-yearly-date:after{clear:both}.fuelux .scheduler .repeat-yearly .repeat-yearly-date .year-month-day{margin-left:10px}.fuelux .scheduler .repeat-yearly .year-month-days{margin-left:10px}.fuelux .scheduler .repeat-yearly .year-month{margin-left:10px}.fuelux .scheduler .repeat-yearly .repeat-yearly-day{margin-top:10px;*zoom:1}.fuelux .scheduler .repeat-yearly .repeat-yearly-day:before,.fuelux .scheduler .repeat-yearly .repeat-yearly-day:after{display:table;content:"";line-height:0}.fuelux .scheduler .repeat-yearly .repeat-yearly-day:after{clear:both}.fuelux .scheduler .repeat-yearly .repeat-yearly-day .repeat-yearly-day-text{margin-left:10px}.fuelux .scheduler .repeat-weekly button:not(.active){background-color:#fff}.fuelux .scheduler .repeat-weekly .btn-group.disabled{position:relative;opacity:.65}.fuelux .scheduler .repeat-weekly .btn-group.disabled:before{background:0 0;bottom:0;content:"";left:0;position:absolute;right:0;top:0;z-index:5}.fuelux .scheduler .selectlist{float:left}.fuelux .scheduler label.radio{float:left;line-height:27px}.fuelux .scheduler label.radio input{margin-top:8px}.fuelux .scheduler .repeat-end .end-after{float:left;display:inline-block;margin-right:10px}.fuelux .scheduler .repeat-end .form-group{margin-left:0}.fuelux .search.disabled .input-group-btn{cursor:not-allowed}.fuelux .selectlist.disabled{cursor:not-allowed}.fuelux .selectlist-sizer{display:inline-block;position:absolute;visibility:hidden;top:0}.fuelux .selectlist .selected-label{overflow:hidden;min-width:2em}.fuelux .selectlist .btn.dropdown-toggle{white-space:normal}.fuelux .selectlist .btn.dropdown-toggle .selected-label{padding-right:10px;text-align:left}.fuelux .tree{border:1px solid #999;border-radius:4px;padding:10px 15px 0;overflow-x:auto;overflow-y:auto;position:relative;list-style:none}.fuelux .tree :focus{outline:0}.fuelux .tree button:focus{color:#999}.fuelux .tree ul{padding-left:0;margin-top:0;margin-bottom:0;list-style:none}.fuelux .tree li{margin:0;margin-top:5px;margin-bottom:5px}.fuelux .tree .tree-loader{margin-left:45px}.fuelux .tree .tree-open>.tree-branch-header .glyphicon-play{transform:rotate(90deg);-ms-transform:rotate(90deg);-webkit-transform:rotate(90deg);position:relative;left:-5px}.fuelux .tree [data-children=false]>.tree-branch-header .icon-caret:before{content:'\00a0'}.fuelux .tree .tree-branch .tree-branch-header{position:relative;border-radius:6px}.fuelux .tree .tree-branch .tree-branch-header .tree-branch-name:hover{color:#999}.fuelux .tree .tree-branch .tree-branch-header .glyphicon-play{font-size:10px;padding-right:5px}.fuelux .tree .tree-branch .tree-branch-header .glyphicon-play:before{position:relative;top:-2px}.fuelux .tree .tree-branch .tree-branch-header .tree-branch-name{white-space:nowrap;border-radius:6px;background-color:transparent;border:0}.fuelux .tree .tree-branch .tree-branch-header label{font-weight:400;padding-left:3px;margin-bottom:0;cursor:pointer}.fuelux .tree .tree-branch .tree-branch-children{margin-left:14px}.fuelux .tree .tree-item{position:relative;cursor:pointer;border-radius:6px;margin-left:26px}.fuelux .tree .tree-item .tree-item-name{white-space:nowrap;border-radius:6px;background-color:transparent;border:0}.fuelux .tree .tree-item .tree-item-name:hover{color:#999}.fuelux .tree .tree-item.tree-selected .tree-item-name{background-color:#4f4f4f;color:#fff}.fuelux .tree .tree-item label{font-weight:400;padding-left:7px;margin-bottom:0;cursor:pointer}.fuelux .tree .icon-caret:hover+.tree-branch-name{color:#999}.fuelux .tree.tree-folder-select .tree-branch .icon-caret{background-color:transparent;border:0}.fuelux .tree.tree-folder-select .tree-branch .icon-caret:hover{cursor:pointer;color:#999}.fuelux .tree.tree-folder-select .tree-branch>.tree-branch-name{padding:1px 5px 0;border-radius:6px}.fuelux .tree.tree-folder-select .tree-branch>.tree-branch-name.tree-selected{background-color:#4f4f4f;color:#fff}.fuelux .tree.tree-folder-select .tree-branch.tree-selected>.tree-branch-header .tree-branch-name{background-color:#4f4f4f;color:#fff}.fuelux .tree.tree-folder-select .tree-branch.tree-selected>.tree-branch-header .tree-branch-name:hover{background-color:#4f4f4f;color:#fff}.fuelux .wizard{*zoom:1;border:1px solid #d4d4d4;border-radius:4px;box-shadow:0 1px 4px rgba(0,0,0,.065);background-color:#f9f9f9;position:relative;min-height:48px;overflow:hidden}.fuelux .wizard:before,.fuelux .wizard:after{display:table;content:"";line-height:0}.fuelux .wizard:after{clear:both}.fuelux .wizard>.steps{list-style:none outside none;padding:0;margin:0;width:4000px}.fuelux .wizard>.steps.previous-disabled li.complete{cursor:default}.fuelux .wizard>.steps.previous-disabled li.complete:hover{background:#f3f4f5;color:#468847;cursor:default}.fuelux .wizard>.steps.previous-disabled li.complete:hover .chevron:before{border-left-color:#f3f4f5}.fuelux .wizard>.steps li{float:left;margin:0;padding:0 20px 0 30px;height:46px;line-height:46px;position:relative;background:#ededed;color:#999;font-size:16px;cursor:not-allowed}.fuelux .wizard>.steps li .chevron{border:24px solid transparent;border-left:14px solid #d4d4d4;border-right:0;display:block;position:absolute;right:-14px;top:0;z-index:1}.fuelux .wizard>.steps li .chevron:before{border:24px solid transparent;border-left:14px solid #ededed;border-right:0;content:"";display:block;position:absolute;right:1px;top:-24px}.fuelux .wizard>.steps li.complete{background:#f3f4f5;color:#468847}.fuelux .wizard>.steps li.complete:hover{background:#e7eff8;cursor:pointer}.fuelux .wizard>.steps li.complete:hover .chevron:before{border-left:14px solid #e7eff8}.fuelux .wizard>.steps li.complete .chevron:before{border-left:14px solid #f3f4f5}.fuelux .wizard>.steps li.active{background:#f1f6fc;color:#3a87ad;cursor:default}.fuelux .wizard>.steps li.active .chevron:before{border-left:14px solid #f1f6fc}.fuelux .wizard>.steps li.active .badge{background-color:#3a87ad}.fuelux .wizard>.steps li .badge{margin-right:8px}.fuelux .wizard>.steps li .badge-success{background-color:#468847}.fuelux .wizard>.steps li:first-child{border-radius:4px 0 0 4px;padding-left:20px}.fuelux .wizard>.actions{z-index:1000;position:absolute;right:0;line-height:46px;float:right;padding-left:15px;padding-right:15px;vertical-align:middle;background-color:#e5e5e5;border-left:1px solid #d4d4d4}.fuelux .wizard>.actions a{line-height:45px;font-size:12px;margin-right:8px}.fuelux .wizard>.actions .btn-prev[disabled]{cursor:not-allowed}.fuelux .wizard>.actions .btn-prev span{margin-right:5px}.fuelux .wizard>.actions .btn-next[disabled]{cursor:not-allowed}.fuelux .wizard>.actions .btn-next span{margin-left:5px}.fuelux .wizard .step-content{border-top:1px solid #D4D4D4;padding:10px;float:left;width:100%}.fuelux .wizard .step-content .step-pane{display:none}.fuelux .wizard .step-content>.active{display:block}.fuelux .wizard .step-content>.active .btn-group .active{display:inline-block}.fuelux .wizard.complete>.actions .glyphicon-arrow-right:before{display:none}.fuelux .wizard.complete>.actions .glyphicon-arrow-right{margin-left:0} /* * A colorselector for Twitter Bootstrap which lets you select a color from a predefined set of colors only. * https://github.com/flaute/bootstrap-colorselector @@ -2103,6 +2123,8 @@ video::-webkit-media-text-track-display { .cc-floating.cc-theme-classic{padding:1.2em;border-radius:5px}.cc-floating.cc-type-info.cc-theme-classic .cc-compliance{text-align:center;display:inline;-ms-flex:none;flex:none}.cc-theme-classic .cc-btn{border-radius:5px}.cc-theme-classic .cc-btn:last-child{min-width:140px}.cc-floating.cc-type-info.cc-theme-classic .cc-btn{display:inline-block} .cc-theme-edgeless.cc-window{padding:0}.cc-floating.cc-theme-edgeless .cc-message{margin:2em 2em 1.5em}.cc-banner.cc-theme-edgeless .cc-btn{margin:0;padding:.8em 1.8em;height:100%}.cc-banner.cc-theme-edgeless .cc-message{margin-left:1em}.cc-floating.cc-theme-edgeless .cc-btn+.cc-btn{margin-left:0} .navbar-head { + background-color: #337ab7; + /* background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); @@ -2110,6 +2132,7 @@ video::-webkit-media-text-track-display { filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); background-repeat: repeat-x; + */ border-color: #245580; } .navbar-head .navbar-brand { @@ -2197,32 +2220,74 @@ hr { color: #eeeeee; } +:root { + --light-mode-body-color: #fff; + --light-mode-primary-color: #fafafa; + --light-mode-highlight-color: #eeeeee; + --light-mode-input-color: #fff; + --light-mode-text-color: #555; + --light-mode-light-text-color: #707070; + --light-mode-divider: #ccc; + + --dark-mode-body-color: #141414; + --dark-mode-primary-color: rgb(36, 37, 38); + --dark-mode-highlight-color: rgb(58, 59, 60); + --dark-mode-input-color: #141414; + --dark-mode-text-color: rgb(222, 226, 230); + --dark-mode-reverse-text-color: #141414; + --dark-mode-light-text-color: #999; + --dark-mode-divider: rgb(62, 64, 66); +} + +@media print { + #maincontent { + margin-left:0px !important; + } + a[href]:after { + content: none !important; + } +} + .modal-dialog { - margin-top: max(10px, env(safe-area-inset-top)); + margin-top: calc(10px + env(safe-area-inset-top)) +} + +th { + font-weight: normal; } @media (min-width: 768px) { .modal-dialog { - margin-top: max(30px, env(safe-area-inset-top)); + margin-top: calc(30px + env(safe-area-inset-top)) } } +a.button-link { + color: #888 !important; + text-decoration: none; + padding: 8px 12px; + border-radius: 4px; + transition: background-color 0.3s ease; +} + +.button-link-group a.button-link { + padding-right: 15px; +} + +a.button-link:hover { + background-color: rgba(0, 123, 255, 0.1); + /* Faint background on hover, change the rgba values as desired */ +} + /* otherwise selects extend to the entire width, which is too wide */ select.form-control { - width: auto; + width: auto; } .scrollable-groups-menu { - height: auto; - max-height: 400px; - overflow-x: hidden; -} - - -/* make current page in pagination blocks stand out */ -.currentpage { - color: #000 !important; - font-weight: 900; + height: auto; + max-height: 400px; + overflow-x: hidden; } @@ -2230,89 +2295,101 @@ select.form-control { text-align: center span, which is what summernote does to align things. so we use inline-block instead. */ .myimg-responsive { - display: inline-block; - max-width: 100%; - height: auto; + display: inline-block; + max-width: 100%; + height: auto; } +.table { + border-radius: 4px; + border-color: #f8f8f8; +} + +.table>tbody>tr:last-child>td:first-child { + border-bottom-left-radius: 4px; +} + +.table>tbody>tr:last-child>td:last-child { + border-bottom-right-radius: 4px; +} /* snug up breadcrumb bottom */ - .breadcrumb { - margin-bottom: 10px; + margin-bottom: 10px; } /* fix for Microsoft Outlook */ p.MsoNormal { - margin: 0px; + margin: 0px; } p.MsoListParagraph { - margin-bottom: 0px; + margin-bottom: 0px; } .the-table { - table-layout: fixed; - word-wrap: break-word; + table-layout: fixed; + word-wrap: break-word; } blockquote { - font-size: 14px; - border-left: 5px solid #eee; + font-size: 16px; + border-left: 5px solid #e0e0e0; } .hidden-label { - font-size: 0; - height: 1px; - overflow: hidden; - display: block; + font-size: 0; + height: 1px; + overflow: hidden; + display: block; } .scroll-top-wrapper { - position: fixed; - opacity: 0; - visibility: hidden; - overflow: hidden; - text-align: center; - z-index: 99999999; - background-color: #777777; - color: #eeeeee; - width: 50px; - height: 48px; - line-height: 48px; - right: 10px; - bottom: 0px; - padding-top: 2px; - border-top-left-radius: 10px; - border-top-right-radius: 10px; - border-bottom-right-radius: 10px; - border-bottom-left-radius: 10px; - -webkit-transition: all 0.5s ease-in-out; - -moz-transition: all 0.5s ease-in-out; - -ms-transition: all 0.5s ease-in-out; - -o-transition: all 0.5s ease-in-out; - transition: all 0.5s ease-in-out; + position: fixed; + opacity: 0; + visibility: hidden; + overflow: hidden; + text-align: center; + z-index: 99999999; + background-color: #707070; + color: #eeeeee; + width: 50px; + height: 48px; + line-height: 48px; + right: 10px; + bottom: 0px; + padding-top: 2px; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + border-bottom-right-radius: 10px; + border-bottom-left-radius: 10px; + -webkit-transition: all 0.5s ease-in-out; + -moz-transition: all 0.5s ease-in-out; + -ms-transition: all 0.5s ease-in-out; + -o-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; } .scroll-top-wrapper:hover { - background-color: #888888; + background-color: #888888; } .scroll-top-wrapper.show { - visibility: visible; - cursor: pointer; - opacity: 0.4; + visibility: visible; + cursor: pointer; + opacity: 0.4; } .scroll-top-wrapper i.fa { - line-height: inherit; + line-height: inherit; } .dropdown-wide { display: block; } + .dropdown-narrow { display: none; } @@ -2320,15 +2397,77 @@ blockquote { /* subject font size */ .subject { - font-size: 17px; + font-size: 17px; } -@media screen and (max-width: 992px) { - .breadcrumb { - margin-left: -15px; - margin-right: -15px; - } - +a, +.pagination>li>a, +.pagination>li>span { + color: #2f6fa7; +} + +.navbar-head, +.list-group-item.active, +.list-group-item.active:focus, +.list-group-item.active:hover, +body.dark-mode .list-group-item.active, +body.dark-mode .list-group-item.active:focus, +body.dark-mode .list-group-item.active:hover { + background-color: #2f6fa7; +} + +body:not(.dark-mode) .groupmaincontent ul.dropdown-menu a, +body:not(.dark-mode) .panel-default>.panel-heading a { + color: #333 !important; +} + +body:not(.dark-mode) a.showvisited:visited, +body:not(.dark-mode) a.button-link, +body:not(.dark-mode) .thread-attribution, +body:not(.dark-mode) .text-muted, +body:not(.dark-mode) .breadcrumb>.active, +body:not(.dark-mode) .help-block, +body:not(.dark-mode) span[id*="likestats"] { + color: #707070 !important; +} + +.likestats { + font-size:14px; + color:#707070; +} + + +.thread-attribution { + font-size:14px; + color:#707070; +} + +body { + font-family: system-ui, + "Segoe UI", + Roboto, + "Helvetica Neue", + "Noto Sans", + "Liberation Sans", + Arial, + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; + font-size: 16px; + font-weight: 400; +} + +#body { + padding-top: calc(60px + env(safe-area-inset-top)); +} + +/* + This is to prevent the header and footer on Safari from moving when scrolling the + page. +*/ +@media (max-width: 992px) { #maincontent { position: absolute; top: calc(55px + env(safe-area-inset-top)); @@ -2337,1230 +2476,1572 @@ blockquote { left: 0; overflow-y: auto !important; } +} - #staticcontent { +#maincontent-refresh { + scroll-margin-top: 60px; +} + +.groupmaincontent { + margin-left: 225px; +} + +.btn-xs { + font-size:12px !important; +} + +.btn-default { + font-size: 14px; + color: rgb(51, 51, 51); + background-color: #ccc; + /*line-height: 15px;*/ + border: 1px solid #ccc; + border-radius: 6px; + transition: all 0.3s ease 0s; +} + +.btn-default:hover { + background-color: #bbb; + border: 1px solid #bbb; + color: rgb(41, 41, 41); +} + +.btn-outline-default { + font-size: 14px; + color: #ccc; + /*line-height: 15px;*/ + border: 2px solid #ccc; + border-radius: 6px; + background: transparent; + transition: all 0.3s ease 0s; +} + +.btn-outline-default:hover { + color: #FFF; + background-color: #ccc; + border: 2px solid #ccc; +} + +.btn-sm { + line-height: 18px; +} + +.btn-primary { + font-size: 14px; + color: #FFF; + /*line-height: 18px;*/ + border: 1px solid #337ab7; + background-color: #337ab7; + border-radius: 6px; + transition: all 0.3s ease 0s; +} + +.btn-primary.active { + background-color: #337ab7; + border-color: #337ab7; +} + +.btn-outline-primary { + font-size: 14px; + color: #337ab7; + /*line-height: 15px;*/ + border: 1px solid #337ab7; + background-color: #337ab7; + border-radius: 6px; + background: transparent; + transition: all 0.3s ease 0s; +} + +.btn-outline-primary.active { + background-color: #337ab7; + border-color: #337ab7; +} + +.btn-outline-primary:hover { + color: #FFF; + background: #337ab7; + border: 1px solid #337ab7; +} + +.btn-success { + font-size: 14px; + color: #FFF; + background-color: #419641; + /*line-height: 15px;*/ + border: 1px solid #419641; + border-radius: 6px; + transition: all 0.3s ease 0s; +} + +.btn-success:hover { + background-color: #307d30; + border: 1px solid #307d30; +} + +.btn-outline-success { + font-size: 14px; + color: #419641; + /*line-height: 15px;*/ + border: 1px solid #419641; + border-radius: 6px; + background: transparent; + transition: all 0.3s ease 0s; +} + +.btn-outline-success:hover { + color: #FFF; + background: #419641; + border: 1px solid #419641; +} + +.btn-outline-success:hover { + color: #FFF; + background: #419641; + border: 1px solid #419641; +} + +.btn-info { + font-size: 14px; + color: #FFF; + background-color: #5bc0de; + /*line-height: 15px;*/ + border: 1px solid #5bc0de; + border-radius: 6px; + transition: all 0.3s ease 0s; +} + +.btn-info:hover { + background-color: #2188a0; + border: 1px solid #2188a0; +} + +.btn-outline-info { + font-size: 14px; + color: #5bc0de; + /*line-height: 15px;*/ + border: 1px solid #5bc0de; + border-radius: 6px; + background: transparent; + transition: all 0.3s ease 0s; +} + +.btn-outline-info:hover { + color: #FFF; + background: #5bc0de; + border: 1px solid #5bc0de; +} + + +.btn-warning { + font-size: 14px; + color: #FFF; + background-color: rgb(245, 128, 62); + /*line-height: 15px;*/ + border: 1px solid rgb(245, 128, 62); + border-radius: 6px; + transition: all 0.3s ease 0s; +} + +.btn-warning:hover { + background-color: #d67f0c; + border: 1px solid #d67f0c; +} + +.btn-outline-warning { + font-size: 14px; + color: rgb(245, 128, 62); + /*line-height: 15px;*/ + border: 1px solid rgb(245, 128, 62); + border-radius: 6px; + background: transparent; + transition: all 0.3s ease 0s; +} + +.btn-outline-warning:hover { + color: #FFF; + background: rgb(245, 128, 62); + border: 1px solid rgb(245, 128, 62); +} + +.btn-danger { + font-size: 14px; + color: #FFF; + background-color: #d9534f; + /*line-height: 15px;*/ + border: 1px solid #d9534f; + border-radius: 6px; + transition: all 0.3s ease 0s; +} + +.btn-danger:hover { + background-color: #a0211d; + border: 1px solid #a0211d; +} + +.btn-outline-danger { + font-size: 14px; + color: #d9534f; + /*line-height: 15px;*/ + border: 1px solid #d9534f; + border-radius: 6px; + background: transparent; + transition: all 0.3s ease 0s; +} + +.btn-outline-danger:hover { + color: #FFF; + background: #d9534f; + border: 1px solid #d9534f; +} + +.scrolling-wrapper { + overflow-x: auto; + white-space: nowrap; +} + +.scrolling-wrapper .btn { + display: inline-block; + white-space: normal; +} + +.Xmce-tinymce { + box-shadow: none !important; +} + +.Xmce-content-body { + margin-top: 10px; + margin-left: 10px; +} + +.Xmce-panel { + border-color: #ccc !important; +} + +.scrollbar { + overflow-y: auto; + max-height: calc(100vh - 61px); + /*visibility: hidden;*/ +} + +.scrollbar-content, +.scrollbar:hover, +.scrollbar:focus { + /*visibility: visible !important; + -webkit-overflow-scrolling: touch;*/ + overflow-y: auto; +} + +.scrollbar::-webkit-scrollbar { + /*-webkit-appearance: none;*/ + width: 6px; + height: 6px; + background-color: rgba(0, 0, 0, 0); +} +.scrollbar::-webkit-scrollbar-thumb { + border-radius: 3px; + background-color: #ccc; +} + +#groupsidebar { + padding-right:0px; + position:fixed; + max-width:220px; + width:100%; + top: calc(60px + env(safe-area-inset-top)); +} + +/* force a passage without spaces to be broken up to fit a fixed width container */ +.forcebreak, .forcebreak * { +/* + word-break: break-all; + overflow-wrap: break-word; + -webkit-hyphens: auto; + -moz-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; +*/ + word-wrap: break-word !important; + overflow-wrap: break-word !important; + /*white-space: normal !important;*/ +} + +@media screen and (max-width: 992px) { + + .breadcrumb { + margin-left: -15px; + margin-right: -15px; + } + /* + .groupmaincontent { + position: absolute; + top: calc(55px + env(safe-area-inset-top)); + bottom: 80px; + right: 0; + left: 0; overflow-y: auto !important; + margin-left: 0px; + margin-right: 0px; + } + */ + .groupmaincontent { + margin-left: 0px; } - /* need to do this because tinymce goes into an iframe and inherits the body overflow */ - .mce-content-bodyXX { + #groupsidebar { + display: none; + } + #staticcontent { overflow-y: auto !important; } .dropdown-wide { display: none; } - + .dropdown-narrow { display: block; } /* fix chat */ #chat-container { - height: calc(100% - 181px - env(safe-area-inset-top)) !important; + height: calc(100% - 50px) !important; } - #chat-unread-counter { - bottom: 201px !important; + + .nav-pills>li { + float: none; + } + + .navbar-fixed-bottom { + margin-bottom: 0px; + } + + .table-responsive { + border: 0px; + } + + /* subject font size bigger than desktop*/ + .subject { + font-size: 18px; + } + + .scroll-top-wrapper { + right: 0px; + bottom: 72px; + } + + /* fix for auto zoom in summernote */ + .note-editor .note-editable { + font-size: 17px; + } + + /* undo this from above because it causes horizontal scrolling */ + select.form-control { + width: 100%; } - .nav-pills>li { - float: none; - } - .navbar-fixed-bottom { - margin-bottom: 0px; - } - .table-responsive { - border: 0px; - } - /* subject font size bigger than desktop*/ - .subject { - font-size: 18px; - } - /* force a passage without spaces to be broken up to fit a fixed width container */ - .forcebreak { - -ms-word-break: break-all; - /* word-break is commented out because it breaks firefox and apparently adds nothing */ - /* word-break: break-all; w*/ - /* Non standard for webkit */ - word-wrap: break-word; - -webkit-hyphens: auto; - -moz-hyphens: auto; - -ms-hyphens: auto; - hyphens: auto; - } - .scroll-top-wrapper { - right: 0px; - bottom: 72px; - } - /* fix for auto zoom in summernote */ - .note-editor .note-editable { - font-size: 16px; - } - /* undo this from above because it causes horizontal scrolling */ - select.form-control { - width: 100%; - } } a.showvisited:visited { - /* visited link */ - color: #787878; + /* visited link */ + color: #787878; } .navbar.center .navbar-inner { - text-align: center; -} -.navbar.center .navbar-inner .nav { - float: none; - display:inline-block; - vertical-align: middle; + text-align: center; } -.noborderlist { - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; +.navbar.center .navbar-inner .nav { + float: none; + display: inline-block; + vertical-align: middle; } .noborderitem:first-child { - border-top: 0px; + border-top-left-radius: 0px !important; + border-top-right-radius: 0px !important; } .noborderitem:last-child { - border-bottom: 0px; + border-bottom: 0px !important; } .noborderitem { - border-right-width: 0px; - border-left-width: 0px; - border-top-left-radius: 0px !important; - border-top-right-radius: 0px !important; - border-bottom-left-radius: 0px !important; - border-bottom-right-radius: 0px !important; + border-right-width: 0px; + border-left-width: 0px; } table.table-fixed { - table-layout: fixed; - width: 100%; + table-layout: fixed; + width: 100%; } /* spacing used for buttons that may wrap to the next line */ .top5 { - margin-top: 5px; + margin-top: 5px; } .top7 { - margin-top: 7px; + margin-top: 7px; } .top10 { - margin-top: 10px; + margin-top: 10px; } .top15 { - margin-top: 15px; + margin-top: 15px; } .top17 { - margin-top: 17px; + margin-top: 17px; } .top30 { - margin-top: 30px; + margin-top: 30px; } .bottom5 { - margin-bottom: 5px; + margin-bottom: 5px; } .bottom7 { - margin-bottom: 7px; + margin-bottom: 7px; } .bottom10 { - margin-bottom: 10px; + margin-bottom: 10px; } .bottom15 { - margin-bottom: 15px; + margin-bottom: 15px; } .bottom17 { - margin-bottom: 17px; + margin-bottom: 17px; } .bottom30 { - margin-bottom: 30px; + margin-bottom: 30px; } .list-group-submenu { - margin-left: 20px; + margin-left: 20px; } +.list-group-subsubmenu { + margin-left: 40px; +} /* hashtag color definitions */ .hashtag-btn { - color: #fff !important; + color: #fff; } .hashtag-label-white { - background-color: #fff; - border-color: #ccc; + background-color: #fff; + border-color: #ccc; } .hashtag-label-green-lantern { - background-color: #61b16c; + background-color: #61b16c; } .hashtag-label-cucumber { - background-color: #91d09a; + background-color: #91d09a; } .hashtag-label-cerulean-blue { - background-color: #4191d6; + background-color: #4191d6; } .hashtag-label-bluejean { - background-color: #8ec2ee; + background-color: #8ec2ee; } .hashtag-label-capri-blue { - background-color: #88ddf7; + background-color: #88ddf7; } .hashtag-label-aquamute { - background-color: #60d2b8; + background-color: #60d2b8; } .hashtag-label-emerald-green { - background-color: #11adb1; + background-color: #11adb1; } .hashtag-label-apricot { - background-color: #fe904b; + background-color: #fe904b; } .hashtag-label-orange { - background-color: #faa849; + background-color: #faa849; } .hashtag-label-yellow { - background-color: #fecd0f; + background-color: #fecd0f; } .hashtag-label-cherry-blossom { - background-color: #f96ab0; + background-color: #f96ab0; } .hashtag-label-peony { - background-color: #fb9bc4; + background-color: #fb9bc4; } .hashtag-label-tomato { - background-color: #f85347; + background-color: #f85347; } .hashtag-label-melon { - background-color: #fa8287; + background-color: #fa8287; } .hashtag-label-orchid { - background-color: #df6cca; + background-color: #df6cca; } .hashtag-label-pink { - background-color: #f39de4; + background-color: #f39de4; } .hashtag-label-lilac { - background-color: #9f8cd5; + background-color: #9f8cd5; } .hashtag-label-purple { - background-color: #837fd5; + background-color: #837fd5; } .hashtag-label-dark-grey { - background-color: #4c4c4c; + background-color: #4c4c4c; } .hashtag-label-light-grey { - background-color: #8c8c8c; + background-color: #8c8c8c; } .hashtag-label-military { - background-color: #938953; + background-color: #938953; } .hashtag-label-light-brown { - background-color: #c4bd97; + background-color: #c4bd97; } .hashtag-label-moss-green { - background-color: #93ad59; + background-color: #93ad59; } .hashtag-label-grey-blue { - background-color: #83adb5; + background-color: #83adb5; } .hashtag-label-green-sage { - background-color: #9fc4ac; + background-color: #9fc4ac; } .hashtag-label-sage { - background-color: #89bfbd; + background-color: #89bfbd; } .hashtag-label-blush { - background-color: #ee836f; + background-color: #ee836f; } .hashtag-label-mustard { - background-color: #cb9228; + background-color: #cb9228; } .hashtag-label-mulbery { - background-color: #d55d75; + background-color: #d55d75; } .hashtag-label-dusty-mauve { - background-color: #655251; + background-color: #655251; } .hashtag-label-dark-orange { - background-color: #e76239; + background-color: #e76239; } .hashtag-label-burnt-yellow { - background-color: #dab71f; + background-color: #dab71f; } .hashtag-label-antique-pink { - background-color: #e5b9b7; + background-color: #e5b9b7; } .hashtag-label-lips { - background-color: #c97586; + background-color: #c97586; } .hashtag-label-terracotta { - background-color: #a7605f; + background-color: #a7605f; } .hashtag-label-cloudy-blue { - background-color: #6381b4; + background-color: #6381b4; } .hashtag-label-purple-grey { - background-color: #8593ab; + background-color: #8593ab; } .hashtag-label-light-lilac { - background-color: #ccc1d9; + background-color: #ccc1d9; } .hashtag-label-grape { - background-color: #5e3c58; + background-color: #5e3c58; } .hashtag-label-purple-blue { - background-color: #4853a1; + background-color: #4853a1; } .hashtag-label-sky { - background-color: #9cc7df; + background-color: #9cc7df; } .hashtag-label-beige { - background-color: #dcc39c; + background-color: #dcc39c; } .hashtag-box-white { - background-color: #fff; - border-color: #ccc; + background-color: #fff !important; + border-color: #ccc; } .hashtag-box-green-lantern { - color: #333 !important; - background-color: #61b16c; + color: #333 !important; + background-color: #61b16c !important; } .hashtag-box-cucumber { - color: #333 !important; - background-color: #91d09a; + color: #333 !important; + background-color: #91d09a !important; } .hashtag-box-cerulean-blue { - color: #333 !important; - background-color: #4191d6; + color: #333 !important; + background-color: #4191d6 !important; } .hashtag-box-bluejean { - color: #333 !important; - background-color: #8ec2ee; + color: #333 !important; + background-color: #8ec2ee !important; } .hashtag-box-capri-blue { - color: #333 !important; - background-color: #88ddf7; + color: #333 !important; + background-color: #88ddf7 !important; } .hashtag-box-aquamute { - color: #333 !important; - background-color: #60d2b8; + color: #333 !important; + background-color: #60d2b8 !important; } .hashtag-box-emerald-green { - color: #333 !important; - background-color: #11adb1; + color: #333 !important; + background-color: #11adb1 !important; } .hashtag-box-apricot { - color: #333 !important; - background-color: #fe904b; + color: #333 !important; + background-color: #fe904b !important; } .hashtag-box-orange { - color: #333 !important; - background-color: #faa849; + color: #333 !important; + background-color: #faa849 !important; } .hashtag-box-yellow { - color: #333 !important; - background-color: #fecd0f; + color: #333 !important; + background-color: #fecd0f !important; } .hashtag-box-cherry-blossom { - color: #333 !important; - background-color: #f96ab0; + color: #333 !important; + background-color: #f96ab0 !important; } .hashtag-box-peony { - color: #333 !important; - background-color: #fb9bc4; + color: #333 !important; + background-color: #fb9bc4 !important; } .hashtag-box-tomato { - color: #333 !important; - background-color: #f85347; + color: #333 !important; + background-color: #f85347 !important; } .hashtag-box-melon { - color: #333 !important; - background-color: #fa8287; + color: #333 !important; + background-color: #fa8287 !important; } .hashtag-box-orchid { - color: #333 !important; - background-color: #df6cca; + color: #333 !important; + background-color: #df6cca !important; } .hashtag-box-pink { - color: #333 !important; - background-color: #f39de4; + color: #333 !important; + background-color: #f39de4 !important; } .hashtag-box-lilac { - color: #333 !important; - background-color: #9f8cd5; + color: #333 !important; + background-color: #9f8cd5 !important; } .hashtag-box-purple { - color: #333 !important; - background-color: #837fd5; + color: #333 !important; + background-color: #837fd5 !important; } .hashtag-box-dark-grey { - color: #eee !important; - background-color: #4c4c4c; + color: #eee !important; + background-color: #4c4c4c !important; } .hashtag-box-light-grey { - color: #333 !important; - background-color: #8c8c8c; + color: #333 !important; + background-color: #8c8c8c !important; } .hashtag-box-military { - color: #333 !important; - background-color: #938953; + color: #333 !important; + background-color: #938953 !important; } .hashtag-box-light-brown { - color: #333 !important; - background-color: #c4bd97; + color: #333 !important; + background-color: #c4bd97 !important; } .hashtag-box-moss-green { - color: #333 !important; - background-color: #93ad59; + color: #333 !important; + background-color: #93ad59 !important; } .hashtag-box-grey-blue { - color: #333 !important; - background-color: #83adb5; + color: #333 !important; + background-color: #83adb5 !important; } .hashtag-box-green-sage { - color: #333 !important; - background-color: #9fc4ac; + color: #333 !important; + background-color: #9fc4ac !important; } .hashtag-box-sage { - color: #333 !important; - background-color: #89bfbd; + color: #333 !important; + background-color: #89bfbd !important; } .hashtag-box-blush { - color: #333 !important; - background-color: #ee836f; + color: #333 !important; + background-color: #ee836f !important; } .hashtag-box-mustard { - color: #333 !important; - background-color: #cb9228; + color: #333 !important; + background-color: #cb9228 !important; } .hashtag-box-mulbery { - color: #333 !important; - background-color: #d55d75; + color: #333 !important; + background-color: #d55d75 !important; } .hashtag-box-dusty-mauve { - color: #eee !important; - background-color: #655251; + color: #eee !important; + background-color: #655251 !important; } .hashtag-box-dark-orange { - color: #333 !important; - background-color: #e76239; + color: #333 !important; + background-color: #e76239 !important; } .hashtag-box-burnt-yellow { - color: #333 !important; - background-color: #dab71f; + color: #333 !important; + background-color: #dab71f !important; } .hashtag-box-antique-pink { - color: #333 !important; - background-color: #e5b9b7; + color: #333 !important; + background-color: #e5b9b7 !important; } .hashtag-box-lips { - color: #333 !important; - background-color: #c97586; + color: #333 !important; + background-color: #c97586 !important; } .hashtag-box-terracotta { - color: #eee !important; - background-color: #a7605f; + color: #eee !important; + background-color: #a7605f !important; } .hashtag-box-cloudy-blue { - color: #333 !important; - background-color: #6381b4; + color: #333 !important; + background-color: #6381b4 !important; } .hashtag-box-purple-grey { - color: #333 !important; - background-color: #8593ab; + color: #333 !important; + background-color: #8593ab !important; } .hashtag-box-light-lilac { - color: #333 !important; - background-color: #ccc1d9; + color: #333 !important; + background-color: #ccc1d9 !important; } .hashtag-box-grape { - color: #eee !important; - background-color: #5e3c58; + color: #eee !important; + background-color: #5e3c58 !important; } .hashtag-box-purple-blue { - color: #eee !important; - background-color: #4853a1; + color: #eee !important; + background-color: #4853a1 !important; } .hashtag-box-sky { - color: #333 !important; - background-color: #9cc7df; + color: #333 !important; + background-color: #9cc7df !important; } .hashtag-box-beige { - color: #333 !important; - background-color: #dcc39c; + color: #333 !important; + background-color: #dcc39c !important; } .fa-6x { - font-size: 6em; + font-size: 6em; } .template { - display: none; + display: none; } .alert-gray { - background-color: #e6e6e6; - color: #333; + background-color: #e6e6e6; + color: #333; } -.stickywiki { - max-height: 100px; - overflow: hidden; - line-height: 20px; - word-wrap: break-word; -} - -.stickywiki>p { - margin-bottom: 20px; -} - -.mce-ico.mce-i-fa { - display: inline-block; - font: normal normal normal 14px/1; - font-family: 'Font Awesome\ 5 Pro'; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +.Xmce-ico.Xmce-i-fa { + display: inline-block; + font: normal normal normal 14px/1; + font-family: 'Font Awesome\ 5 Pro'; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } .mobilebadge { - position: absolute; - top: -5px; - right: -10px; - color: white; - background-color:#d43f3a; + position: absolute; + top: -5px; + right: -10px; + color: white; + background-color: #d43f3a; border: 2px solid white; } + .groupsbadge { background-color: #d43f3a; - position: absolute; - top: 0px; + position: absolute; + top: 0px; } @media screen and (max-width: 515px) { - .mce-window { - max-width: 320px !important; - left: calc(50% - 160px) !important; - } - .mce-window-body { - max-width: 100% !important; - min-height: 230px !important; - } - .mce-container.mce-panel.mce-abs-layout-item, - .mce-container.mce-panel.mce-abs-layout-item .mce-container-body.mce-abs-layout { - max-width: 100% !important; - min-height: 190px !important; - } - .mce-flow-layout { - text-align: center !important; - } - .mce-flow-layout-item.mce-btn-group { - border-left: none !important; - } - .mce-floatpanel, - .mce-floatpanel>.mce-container-body, - .mce-foot, - .mce-foot>.mce-abs-layout { - max-width: 320px !important; - text-align: center; - } - .mce-formitem { - width: 300px !important; - left: 10px !important; - display: block !important; - } - .mce-formitem:nth-child(2) { - top: 10px !important; - } - .mce-formitem:nth-child(3) { - top: 50px !important; - } - .mce-formitem:nth-child(4) { - top: 90px !important; - } - .mce-formitem:nth-child(5) { - top: 130px !important; - } - .mce-formitem:nth-child(6) { - top: 170px !important; - } - .mce-container.mce-form.mce-abs-layout-item .mce-container-body.mce-abs-layout .mce-container.mce-form.mce-abs-layout-item { - top: 40px !important; - left: 0 !important; - height: 160px !important; - } - .mce-formitem label { - width: 106px !important; - font-size: 13px !important; - left: 0px !important; - } - .mce-multiline { - max-width: 290px !important; - } - .mce-checkbox { - top: 40px !important; - left: 0 !important; - } - .mce-label { - font-size: 13px !important; - } - .mce-foot .mce-btn-has-text { - position: relative !important; - top: 0 !important; - left: 0 !important; - display: inline-block !important; - margin: 10px 5px !important; - } - .mce-abs-layout-item input { - max-width: 150px !important; - } - .mce-abs-layout-item.mce-has-open input { - max-width: 118px !important; - } + .Xmce-window { + max-width: 320px !important; + left: calc(50% - 160px) !important; + } + + .Xmce-window-body { + max-width: 100% !important; + min-height: 230px !important; + } + + .Xmce-container.Xmce-panel.Xmce-abs-layout-item, + .Xmce-container.Xmce-panel.Xmce-abs-layout-item .Xmce-container-body.Xmce-abs-layout { + max-width: 100% !important; + min-height: 190px !important; + } + + .Xmce-flow-layout { + text-align: center !important; + } + + .Xmce-flow-layout-item.Xmce-btn-group { + border-left: none !important; + } + + .Xmce-floatpanel, + .Xmce-floatpanel>.Xmce-container-body, + .Xmce-foot, + .Xmce-foot>.Xmce-abs-layout { + max-width: 320px !important; + text-align: center; + } + + .Xmce-formitem { + width: 300px !important; + left: 10px !important; + display: block !important; + } + + .Xmce-formitem:nth-child(2) { + top: 10px !important; + } + + .Xmce-formitem:nth-child(3) { + top: 50px !important; + } + + .Xmce-formitem:nth-child(4) { + top: 90px !important; + } + + .Xmce-formitem:nth-child(5) { + top: 130px !important; + } + + .Xmce-formitem:nth-child(6) { + top: 170px !important; + } + + .Xmce-container.Xmce-form.Xmce-abs-layout-item .Xmce-container-body.Xmce-abs-layout .Xmce-container.Xmce-form.Xmce-abs-layout-item { + top: 40px !important; + left: 0 !important; + height: 160px !important; + } + + .Xmce-formitem label { + width: 106px !important; + font-size: 14px !important; + left: 0px !important; + } + + .Xmce-multiline { + max-width: 290px !important; + } + + .Xmce-checkbox { + top: 40px !important; + left: 0 !important; + } + + .Xmce-label { + font-size: 14px !important; + } + + .Xmce-foot .Xmce-btn-has-text { + position: relative !important; + top: 0 !important; + left: 0 !important; + display: inline-block !important; + margin: 10px 5px !important; + } + + .Xmce-abs-layout-item input { + max-width: 150px !important; + } + + .Xmce-abs-layout-item.Xmce-has-open input { + max-width: 118px !important; + } } .toc ol { - counter-reset: item + counter-reset: item } .toc li { - display: block; - color: #aaa; + display: block; + color: #aaa; } .toc li:before { - content: counters(item, ".") " "; - counter-increment: item; - color: #000; + content: counters(item, ".") " "; + counter-increment: item; + color: #000; } -.visitedlinks a:visited { - color: #787878; +.wikidisplay a { + text-decoration: underline; +} + +.wikidisplay a:visited { + color: #787878; } .StripeElement--focus.StripeElement--invalid { - box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px inset, rgb(206, 132, 131) 0px 0px 6px; - border-color: rgb(132, 53, 52); + box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px inset, rgb(206, 132, 131) 0px 0px 6px; + border-color: rgb(132, 53, 52); } .StripeElement--focus { - border-color: #66afe9; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); + border-color: #66afe9; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); } .strike { - display: block; - text-align: center; - overflow: hidden; - white-space: nowrap; + display: block; + text-align: center; + overflow: hidden; + white-space: nowrap; } .strike>span { - position: relative; - display: inline-block; + position: relative; + display: inline-block; } .strike>span:before, .strike>span:after { - content: ""; - position: absolute; - top: 50%; - width: 9999px; - height: 1px; - background: #d3d3d3; + content: ""; + position: absolute; + top: 50%; + width: 9999px; + height: 1px; + background: #d3d3d3; } .strike>span:before { - right: 100%; - margin-right: 15px; + right: 100%; + margin-right: 15px; } .strike>span:after { - left: 100%; - margin-left: 15px; + left: 100%; + margin-left: 15px; } .scrollable-menu { - height: auto; - max-height: 200px; - overflow-x: hidden; + height: auto; + max-height: 200px; + overflow-x: hidden; } .template { - display: none; + display: none; } .nomargin { - margin-bottom: 0px; + margin-bottom: 0px; } .help-block { - margin-bottom: 0px; + margin-bottom: 0px; } .fa-stack-1x { - top: .25em; + top: .25em; } .fa-stack { - font-size: .5em; - vertical-align: -16%; + font-size: .5em; + vertical-align: -16%; } .filetype-text { - font-size: .7em; - font-weight: 700; - font-family: 'Oswald'; + font-size: .7em; + font-weight: 700; + font-family: 'Oswald'; } /* remove extra file upload icon, make placeholder text smaller, for file upload widget */ .kv-file-upload { - display: none + display: none } .file-drop-zone-title { - font-size: 30px; + font-size: 30px; } .btn-file { - position: relative; - overflow: hidden; + position: relative; + overflow: hidden; + font-size: 14px !important; } .btn-file input[type=file] { - position: absolute; - top: 0; - right: 0; - min-width: 100%; - min-height: 100%; - font-size: 100px; - text-align: right; - filter: alpha(opacity=0); - opacity: 0; - outline: none; - background: white; - cursor: inherit; - display: block; + position: absolute; + top: 0; + right: 0; + min-width: 100%; + min-height: 100%; + text-align: right; + filter: alpha(opacity=0); + opacity: 0; + outline: none; + background: white; + cursor: inherit; + display: block; + font-size: 14px; } .clearfix:before, .clearfix:after { - content: " "; - display: table; - /* 2 */ + content: " "; + display: table; + /* 2 */ } .clearfix:after { - clear: both; + clear: both; } .clearfix { - *zoom: 1; + *zoom: 1; } .options { - margin-bottom: 8px; + margin-bottom: 8px; } .wrapper { - max-width: 140px; - max-height: 140px; + max-width: 140px; + max-height: 140px; } .imgthumb { - max-width: 100%; - max-height: 100%; - width: auto; + max-width: 100%; + max-height: 100%; + width: auto; } .btn-colorselector { - border-style: solid; - border-color: black; + border-style: solid; + border-color: black; } .popover { - max-width: 100%; - width: 500px; + max-width: 100%; + width: 500px; } .hideme { - display: none; + display: none; } .fc-list-table { - word-break: break-word; + word-break: break-word; } .fc-h-event .fc-event-time { - overflow: visible; + overflow: visible; } + .F { - table-layout: fixed; - width: 100%; + table-layout: fixed; + width: 100%; } .panel-collapsable a:after { - font-family:'Glyphicons Halflings'; - content:"\e114"; - float: right; - color: grey; + font-family: 'Glyphicons Halflings'; + content: "\e114"; + float: right; + color: grey; } + .panel-collapsable a.collapsed:after { - content:"\e080"; -} -.panel-titleDISABLED { - font-weight: 400; -} -labelDISABLED { - font-weight: normal; + content: "\e080"; } /* feed page */ .feed-square { - position: relative; - width: 100px; - height: 100px; - margin:0.50%; - overflow:hidden; + position: relative; + width: 100px; + height: 100px; + margin: 0.50%; + overflow: hidden; } + .feed-mycontent { - position:absolute; - height:100%; /* = 100% - 2*5% padding */ - width:100%; /* = 100% - 2*5% padding */ - padding-left: 2%; - + position: absolute; + height: 100%; + /* = 100% - 2*5% padding */ + width: 100%; + /* = 100% - 2*5% padding */ + padding-left: 2%; + } -.feed-mytable{ - display:table; - width:100%; - height:100%; + +.feed-mytable { + display: table; + width: 100%; + height: 100%; } -.feed-table-cell{ - display:table-cell; - vertical-align:bottom; + +.feed-table-cell { + display: table-cell; + vertical-align: bottom; } + /* For responsive images */ -.feed-mycontent .rs{ - width:auto; - height:auto; - max-height:90%; - max-width:100%; +.feed-mycontent .rs { + width: auto; + height: auto; + max-height: 90%; + max-width: 100%; } + /* For responsive images as background */ -.feed-bg{ - background-position:center center; - background-repeat:no-repeat; - background-size:cover; /* you change this to "contain" if you don't want the images to be cropped */ +.feed-bg { + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + /* you change this to "contain" if you don't want the images to be cropped */ +} + +.feed-mylink { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 1; } -.feed-mylink{ - position:absolute; - width:100%; - height:100%; - top:0; - left: 0; - z-index: 1; -} /* album page */ .album-header { - float:left; - position: relative; - width: 100%; - min-height:250px; - margin-bottom:10px; - overflow:hidden; + float: left; + position: relative; + width: 100%; + min-height: 250px; + margin-bottom: 10px; + overflow: hidden; } + .photos-square { - float:left; - position: relative; - width: 24%; - padding-bottom : 24%; /* = width for a 1:1 aspect ratio */ - margin:0.50%; - overflow:hidden; + float: left; + position: relative; + width: 24%; + padding-bottom: 24%; + /* = width for a 1:1 aspect ratio */ + margin: 0.50%; + overflow: hidden; + border-radius:4px; } + .photos-mycontent { - position:absolute; - height:100%; /* = 100% - 2*5% padding */ - width:100%; /* = 100% - 2*5% padding */ - padding: 5%; - + position: absolute; + height: 100%; + /* = 100% - 2*5% padding */ + width: 100%; + /* = 100% - 2*5% padding */ + padding: 5%; + } -.photos-mytable{ - display:table; - width:100%; - height:100%; + +.photos-mytable { + display: table; + width: 100%; + height: 100%; } -.photos-table-cell{ - display:table-cell; - vertical-align:bottom; + +.photos-table-cell { + display: table-cell; + vertical-align: bottom; } + /* For responsive images */ -.photos-mycontent .rs{ - width:auto; - height:auto; - max-height:90%; - max-width:100%; +.photos-mycontent .rs { + width: auto; + height: auto; + max-height: 90%; + max-width: 100%; } + /* For responsive images as background */ -.photos-bg{ - background-position:center center; - background-repeat:no-repeat; - background-size:cover; /* you change this to "contain" if you don't want the images to be cropped */ +.photos-bg { + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + /* you change this to "contain" if you don't want the images to be cropped */ +} + +.photos-mylink { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 1; } -.photos-mylink{ - position:absolute; - width:100%; - height:100%; - top:0; - left: 0; - z-index: 1; -} /* single photo */ .singlephoto-square { - float:left; - position: relative; - width: 100%; - padding-bottom : 70%; /* = width for a 1:1 aspect ratio */ - min-height:200px; - margin:0.50%; + float: left; + position: relative; + width: 100%; + padding-bottom: 70%; + /* = width for a 1:1 aspect ratio */ + min-height: 200px; + margin: 0.50%; } .singlephoto-mycontent { - position:absolute; - height:100%; /* = 100% - 2*5% padding */ - width:100%; /* = 100% - 2*5% padding */ + position: absolute; + height: 100%; + /* = 100% - 2*5% padding */ + width: 100%; + /* = 100% - 2*5% padding */ } -.singlephoto-mytable{ - display:table; - width:100%; - height:100%; + +.singlephoto-mytable { + display: table; + width: 100%; + height: 100%; } -.singlephoto-table-cell{ - display:table-cell; - vertical-align:middle; + +.singlephoto-table-cell { + display: table-cell; + vertical-align: middle; } + .singlephoto-table-cell a { - color: white; - display: block; - min-height:100%; - width:100%; + color: white; + display: block; + min-height: 100%; + width: 100%; } /* For responsive images */ -.singlephoto-mycontent .rs{ - width:auto; - height:auto; - max-height:90%; - max-width:100%; +.singlephoto-mycontent .rs { + width: auto; + height: auto; + max-height: 90%; + max-width: 100%; } + /* For responsive images as background */ -.singlephoto-bg{ - background-position:center center; - background-repeat:no-repeat; - background-size:contain; /* you change this to "contain" if you don't want the images to be cropped */ +.singlephoto-bg { + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + /* you change this to "contain" if you don't want the images to be cropped */ } /* edit wiki page */ .wikiphoto-modal-body { - max-height: calc(100vh - 212px); - overflow-y: auto; + max-height: calc(100vh - 212px); + overflow-y: auto; } + .wikiphoto-square { - float:left; - position: relative; - width: 30%; - padding-bottom : 30%; /* = width for a 1:1 aspect ratio */ - margin:1.66%; - background-position:center center; - background-repeat:no-repeat; - background-size:cover; /* you change this to "contain" if you don't want the images to be cropped */ - border: 4px solid #ffffff; + float: left; + position: relative; + width: 30%; + padding-bottom: 30%; + /* = width for a 1:1 aspect ratio */ + margin: 1.66%; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + /* you change this to "contain" if you don't want the images to be cropped */ + border: 4px solid #ffffff; } + .wikiphoto-selected { - border: 4px solid #668eaa; + border: 4px solid #668eaa; } /* group home */ .grouphome-fit { - max-width: 100%; - max-height: 100%; + max-width: 100%; + max-height: 100%; } + .grouphome-center { - display: block; - margin: auto; + display: block; + margin: auto; } /* database table */ .dbtable { - border-top: none; - border-bottom: none; - background-color: #FFF; + border-top: none; + border-bottom: none; + background-color: #FFF; } /* chat page autocomplete */ .ui-autocomplete { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - max-height: 400px; - overflow-y: scroll; - padding: 5px 0; - margin: 2px 0 0; - list-style: none; - font-size: 14px; - text-align: left; - background-color: #ffffff; - border: 1px solid #cccccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - background-clip: padding-box; + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + max-height: 400px; + overflow-y: scroll; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; } -.ui-autocomplete > li > div { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.42857143; - color: #333333; - white-space: nowrap; +.ui-autocomplete>li>div { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; } .ui-state-hover, .ui-state-active, .ui-state-focus { - text-decoration: none; - color: #262626; - background-color: #f5f5f5; - cursor: pointer; + text-decoration: none; + color: #262626; + background-color: #f5f5f5; + cursor: pointer; } .ui-helper-hidden-accessible { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; } .event-dot { - display: inline-block; - width: 10px; - height: 10px; - border-radius: 5px; + display: inline-block; + width: 10px; + height: 10px; + border-radius: 5px; } .album-owner a { - color: white; + color: white; } /* mobile hamburger drawer */ .drawer { - display: none; + display: none; } + .drawer__header { - padding: 1.5rem; - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid #ddd; + padding: 1.5rem; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid #ddd; } .drawer__close { - margin: 0; - padding: 0; - border: none; - background-color: transparent; - cursor: pointer; - background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='16px' viewBox='0 0 15 16' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='2.-Menu' transform='translate(-15.000000, -13.000000)' stroke='%23000000'%3E%3Cg id='Group' transform='translate(15.000000, 13.521000)'%3E%3Cpath d='M0,0.479000129 L15,14.2971819' id='Path-3'%3E%3C/path%3E%3Cpath d='M0,14.7761821 L15,-1.24344979e-14' id='Path-3'%3E%3C/path%3E%3C/g%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); - width: 15px; - height: 15px; + margin: 0; + padding: 0; + border: none; + background-color: transparent; + cursor: pointer; + background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='16px' viewBox='0 0 15 16' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cg id='Page-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cg id='2.-Menu' transform='translate(-15.000000, -13.000000)' stroke='%23000000'%3E%3Cg id='Group' transform='translate(15.000000, 13.521000)'%3E%3Cpath d='M0,0.479000129 L15,14.2971819' id='Path-3'%3E%3C/path%3E%3Cpath d='M0,14.7761821 L15,-1.24344979e-14' id='Path-3'%3E%3C/path%3E%3C/g%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); + width: 15px; + height: 15px; } .drawer__wrapper { - position: fixed; - top: 0; - right: 0; - bottom: 0; - height: 100%; - width: 100%; - max-width: 500px; - z-index: 9999; - overflow: auto; - transition: transform 0.3s; - will-change: transform; - background-color: #fff; - display: flex; - flex-direction: column; - -webkit-transform: translateX(103%); - transform: translateX(103%); /* extra 3% because of box-shadow */ - -webkit-overflow-scrolling: touch; /* enables momentum scrolling in iOS overflow elements */ - box-shadow: 0 2px 6px #777; - padding-top: max(0px, env(safe-area-inset-top)); + position: fixed; + top: 0; + right: 0; + bottom: 0; + height: 100%; + width: 100%; + max-width: 500px; + z-index: 9999; + overflow: auto; + transition: transform 0.3s; + will-change: transform; + background-color: #fff; + display: flex; + flex-direction: column; + -webkit-transform: translateX(103%); + transform: translateX(103%); + /* extra 3% because of box-shadow */ + -webkit-overflow-scrolling: touch; + /* enables momentum scrolling in iOS overflow elements */ + box-shadow: 0 2px 6px #707070; + padding-top: max(0px, env(safe-area-inset-top)); } .drawer__content { - position: relative; - overflow-x: hidden; - overflow-y: auto; - height: 100%; - flex-grow: 1; - padding: 1.5rem; + position: relative; + overflow-x: hidden; + overflow-y: auto; + height: 100%; + flex-grow: 1; + padding: 1.5rem; } .drawer.is-active { - display: inline-block; + display: inline-block; } .drawer.is-visible .drawer__wrapper { - -webkit-transform: translateX(0); - transform: translateX(0); + -webkit-transform: translateX(0); + transform: translateX(0); } .drawer.is-visible .drawer__overlay { - opacity: 0.5; + opacity: 0.5; } .drawer__overlay { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - width: 100%; - z-index: 200; - opacity: 0; - transition: opacity 0.3s; - will-change: opacity; - background-color: #000; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + z-index: 200; + opacity: 0; + transition: opacity 0.3s; + will-change: opacity; + background-color: #000; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } .drawer--left .drawer__wrapper { - left: 0; - right: auto; - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); + left: 0; + right: auto; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); } .drawer--bottom .drawer__wrapper { @@ -3577,23 +4058,9 @@ labelDISABLED { /* extra 3% because of box-shadow */ } -@supports (font: -apple-system-body) { - /* in the future to support dynamic text, will require additional work */ - body.appXX { - font: -apple-system-body !important; - font-size: 1rem; - line-height: initial; - } -} - -body.app { - padding-top: calc(60px + env(safe-area-inset-top)); - /*padding-left: max(12px, env(safe-area-inset-left)); - padding-right: max(12px, env(safe-area-inset-right));*/ -} body.app .navbar-fixed-top { - padding-top: max(0px, env(safe-area-inset-top)); - /*padding-bottom: max(20px, env(safe-area-inset-bottom));*/ + padding-top: max(0px, env(safe-area-inset-top)); + /*padding-bottom: max(20px, env(safe-area-inset-bottom));*/ } /* attachment display */ @@ -3664,6 +4131,7 @@ body.app .navbar-fixed-top { .attachment-box:hover .attachment-name-hover { opacity: 1; } + .delete-checkbox { position: absolute; top: 5px; @@ -3671,7 +4139,8 @@ body.app .navbar-fixed-top { } /* files move tree */ -.tree, .tree ul { +.tree, +.tree ul { margin: 0; padding: 0; list-style: none @@ -3743,16 +4212,25 @@ body.app .navbar-fixed-top { outline: 0; } +.maincontent-column { + height:100%; +} +.maincontent-chat-column { + overflow-y: auto; + height: 100%; + padding-right: 0px; + padding-left: 0px; +} + /* chat */ #chat-container { display: flex; flex-direction: column; width: 100%; - height: calc(100% - 50px); + height: calc(100% - 39px); margin: 0 auto; box-sizing: border-box; font-size: 17px; - font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; } #chat-messages { @@ -3811,7 +4289,7 @@ body.app .navbar-fixed-top { } .chat-message.sent .chat-message-content { - background-color: rgb(5,133,148); + background-color: rgb(5, 133, 148); color: rgb(224, 231, 243); } @@ -3886,6 +4364,10 @@ body.app .navbar-fixed-top { z-index: 10; } +.chat-emoji-box a { + text-decoration: none !important; +} + .chat-emoji { font-size: 1.4rem; margin-right: 5px; @@ -3927,6 +4409,7 @@ body.app .navbar-fixed-top { border: 1px solid #ccc; overflow: hidden; min-height: 34px; + outline: none; } #chat-username-popup { @@ -3946,7 +4429,7 @@ body.app .navbar-fixed-top { .chat-reply-bubble-us { padding: 0px 10px 0px 10px; - color: rgb(51,51,51); + color: rgb(51, 51, 51); background-color: rgb(245, 245, 245); width: 100% } @@ -3969,6 +4452,7 @@ body.app .navbar-fixed-top { cursor: pointer; } +/* .chat-html { height: 100%; } @@ -3989,11 +4473,20 @@ body.app .navbar-fixed-top { } .chat-maincontent { - height: 100%; + height: 100vh; padding-right: 0px; padding-left: 0px; padding-bottom: 0px; } +*/ + +.expanded-message { + border-radius:4px; + padding:10px; + border-width:1px; + border-style:solid; + border-color:#f8f8f8; +} /* htmx */ .load-indicator { @@ -4130,7 +4623,8 @@ body.app .navbar-fixed-top { /* Reduced width */ padding: 0 40px; /* Padding added */ - padding-top: env(safe-area-inset-top);} + padding-top: env(safe-area-inset-top); +} .viewer-arrow { color: #FFF; @@ -4233,6 +4727,31 @@ body.app .navbar-fixed-top { color: white; } +.truncate-one-line { + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + overflow: hidden; +} +.truncate-two-lines { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} +.truncate-three-lines { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} +.truncate-four-lines { + display: -webkit-box; + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; + overflow: hidden; +} + .database-truncate-cell { position: relative; line-height: 1.2em; @@ -4243,7 +4762,6 @@ body.app .navbar-fixed-top { padding-bottom: 1.2em; /* Equal to line height to make space for 'Show More' link */ } - .database-text-container { display: -webkit-box; -webkit-line-clamp: 2; @@ -4251,34 +4769,1230 @@ body.app .navbar-fixed-top { overflow: hidden; text-overflow: ellipsis; } - .database-show-more { display: none; } +.list-group-item.sidebar-item { + border: none !important; + padding-top: 8px; + padding-bottom: 8px; +} + +.list-group-item.sidebar-section { + border: none !important; + padding-top: 8px; + padding-bottom: 8px; +} + +.list-group-item.sidebar-section:hover { + background-color: transparent; +} + +.list-group-item>.badge { + float: none; +} + +.sidebar-divider-padding { + padding-top:8px; + padding-bottom:8px; +} + +.sidebar-item-divider { + border: none; + height: 1px; + background-color: #ccc; + padding-top: 1px; + padding-bottom: 1px; +} + +.sidebar-item-divider-label { + font-size:12px; + margin-left:20px; + margin-right:0px; + color: #707070; +} + +.sidebar-item-divider-hr { + margin-top: 10px; + margin-bottom: 0px; + border-top-color: #ccc; +} + +.sidebar-item-smalldivider { + border: none; + height: 1px; + background-color: #ccc; + padding-top: 1px; + padding-bottom: 1px; + width: 90%; + margin: auto; +} + +.autocomplete-highlight { + font-weight: bold; +} + +.autocomplete-list-item { + padding: 5px; + cursor: pointer; + font-size: 16px; + border: 0px; +} + +.autocomplete-list-item:not(.no-hover):hover { + background-color: #337ab7; + color: #fff; +} + + +.tooltip-inner { + text-align: left; + background-color: rgb(36,37,38); +} +.tooltip-arrow { + border-top-color: rgb(36,37,38) !important; +} + +.large-tooltip + .tooltip .tooltip-inner { + min-width: 400px !important; +} + +.hashtag-position { + position: relative; + top: -2px; +} + +.list-group-item-nohover:hover { + background-color: transparent !important; +} + +@media (min-width: 1200px) { + + .col-xl-1, + .col-xl-2, + .col-xl-3, + .col-xl-4, + .col-xl-5, + .col-xl-6, + .col-xl-7, + .col-xl-8, + .col-xl-9, + .col-xl-10, + .col-xl-11, + .col-xl-12 { + float: left; + } + + .col-xl-12 { + width: 100%; + } + + .col-xl-11 { + width: 91.66666667%; + } + + .col-xl-10 { + width: 83.33333333%; + } + + .col-xl-9 { + width: 75%; + } + + .col-xl-8 { + width: 66.66666667%; + } + + .col-xl-7 { + width: 58.33333333%; + } + + .col-xl-6 { + width: 50%; + } + + .col-xl-5 { + width: 41.66666667%; + } + + .col-xl-4 { + width: 33.33333333%; + } + + .col-xl-3 { + width: 25%; + } + + .col-xl-2 { + width: 16.66666667%; + } + + .col-xl-1 { + width: 8.33333333%; + } +} +.calendar-date { + width: 65px; + text-align: center; + border-radius: 4px; + display:inline-block; + vertical-align:top; +} + +.calendar-date .calendar-month { + background-color: rgb(230, 55, 87); + border-radius: 4px 4px 0 0; + padding: 2px; + font-weight: 600; +} + +.calendar-date .calendar-day { + border: 2px solid rgba(230, 55, 87, 0.3); + border-top: 0; + border-radius: 0 0 4px 4px; + font-weight: 700; +} + +.sticky-sidebar { + position: -webkit-sticky; + position: sticky; + top: calc(70px + env(safe-area-inset-top)); +} + +/* pulled in from Bootstrap 5 */ .fs-1 { font-size: 40px; } - -/* Larger */ .fs-2 { font-size: 32px; } - .fs-3 { font-size: 28px; } - .fs-4 { font-size: 24px; } - .fs-5 { font-size: 20px; } - -/* Default */ .fs-6 { font-size: 16px; } +.fs-7 { + font-size: 14px; +} + +.mt-0 { + margin-top: 0 !important; +} +.mb-0 { + margin-bottom: 0 !important; +} +.my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; +} +.ms-0 { + margin-left: 0 !important; +} +.me-0 { + margin-right: 0 !important; +} +.mx-0 { + margin-left: 0 !important; + margin-right: 0 !important; +} + +.pt-0 { + padding-top: 0 !important; +} + +.pb-0 { + padding-bottom: 0 !important; +} + +.py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.ps-0 { + padding-left: 0 !important; +} + +.pe-0 { + padding-right: 0 !important; +} + +.px-0 { + padding-left: 0 !important; + padding-right: 0 !important; +} + +.Xmce-statusbar { + border:0 !important; +} + +.Xmce-panel { + border-color: rgb(204,204,204); +} + +.select2-selection, +.select2-selection__arrow { + height: 33px !important; +} + +.select2-selection__rendered { + line-height: 31px !important +} + +.background-color { + background-color: var(--light-mode-body-color) !important; +} + +.primary-background-color { + background-color: var(--light-mode-primary-color); +} + +.highlight-background-color { + background-color: var(--light-mode-highlight-color); +} + +.table-background-color { + background-color: var(--light-mode-primary-color); +} + +.table-highlight-background-color { + background-color: var(--light-mode-highlight-color); +} + +.panel { + background-color: var(--light-mode-primary-color); +} + +.panel-default { + background-color: var(--light-mode-primary-color); + border-color: var(--light-mode-primary-color); +} + +.panel-interior { + background-color: var(--light-mode-body-color) !important; +} + +.panel-default .panel-heading { + background-color: var(--light-mode-highlight-color); + border-color: var(--light-mode-divider); + border-bottom-width:0px; +} + +.panel-default .panel-footer { + background-color: var(--light-mode-highlight-color); + border-color: var(--light-mode-divider); +} + +.table { + background-color: var(--light-mode-primary-color); + border-color: var(--light-mode-divider); +} + +thead { + background-color: var(--light-mode-highlight-color); +} + +/* Striped Table Rows */ +.table-striped>tbody>tr:nth-of-type(odd) { + background-color: var(--light-mode-primary-color); + /* Darker stripe for odd rows */ +} + +.table-striped>tbody>tr:nth-of-type(even) { + background-color: var(--light-mode-highlight-color); + /* Lighter stripe for even rows */ +} + +.table th, +.table td { + border-color: var(--light-mode-divider); +} + +.table-bordered { + border: 0px; +} + +/* Target the first th of thead for top-left corner */ +.table thead th:first-child { + border-top-left-radius: 4px; + /* Adjust this value as needed */ +} + +/* Target the last th of thead for top-right corner */ +.table thead th:last-child { + border-top-right-radius: 4px; + /* Adjust this value as needed */ +} + +/* Step 1: Style the elements of the first row of every table */ +.table>tbody>tr:first-child>td { + border-radius: 4px; + border-top-width: 0px; +} + +.table>thead>tr>th, +.table>thead>tr>td { + border-bottom-width: 0px; +} + +.transparent-editor { + opacity: 0.4; +} + +.tox-textfield, +.tox-toolbar-textfield { + background-color: rgb(255,255,255) !important; +} + +.feed-border { + border-bottom: 1px solid #eee; +} + + +.navbar-vertical .dropdown-indicator { + padding-right: 1rem !important; +} + +.dropdown-indicator { + position: relative; +} + +.dropdown-indicator[aria-expanded=true]:after { + -webkit-transform: translateY(-50%) rotate(225deg); + -ms-transform: translateY(-50%) rotate(225deg); + transform: translateY(-50%) rotate(225deg); +} + +.dropdown-indicator:after { + content: ""; + display: block; + position: absolute; + left: 190px; + height: .8rem; + width: .8rem; + border-right: 2px solid var(--light-mode-text-color); + border-bottom: 2px solid var(--light-mode-text-color); + top: 50%; + -webkit-transform: translateY(-50%) rotate(45deg); + -ms-transform: translateY(-50%) rotate(45deg); + transform: translateY(-50%) rotate(45deg); + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; + -webkit-transform-origin: center; + -ms-transform-origin: center; + transform-origin: center; + -webkit-transition-property: border-color, -webkit-transform; + transition-property: border-color, -webkit-transform; + -o-transition-property: transform, border-color; + transition-property: transform, border-color; + transition-property: transform, border-color, -webkit-transform; +} + +body.dark-mode .dropdown-indicator:after { + border-right-color: var(--dark-mode-text-color); + border-bottom-color: var(--dark-mode-text-color); +} + +body.dark-mode .feed-border { + border-bottom: 1px solid var(--dark-mode-divider); +} + +body.dark-mode .label-primary { + color: rgb(255,255,255) !important; +} + +body.dark-mode .label-info { + background-color: #3da8c0; + border-color: #3da8c0; +} + +body.dark-mode { + background-color: var(--dark-mode-body-color); + color: var(--dark-mode-text-color); +} + +body.dark-mode .background-color { + background-color: var(--dark-mode-body-color) !important; +} + +body.dark-mode .primary-background-color { + background-color: var(--dark-mode-primary-color); +} +body.dark-mode .highlight-background-color { + background-color: var(--dark-mode-highlight-color); +} +body.dark-mode .table-background-color { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .table-highlight-background-color { + background-color: var(--dark-mode-highlight-color); +} + +body.dark-mode a { + color: #7da8d4; +} + +body.dark-mode a:hover, +body.dark-mode a:focus { + color: #4a7ca3; +} + +body.dark-mode a.showvisited:visited, +body.dark-mode a.button-link, +body.dark-mode .wikidisplay a:visited, +body.dark-mode .thread-attribution, +body.dark-mode .truncate-two-lines+div, +body.dark-mode .text-muted, +body.dark-mode .breadcrumb>.active, +body.dark-mode .help-block { + color: #999999 !important; +} + +body.dark-mode pre { + color: var(--dark-mode-text-color); + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode h1, +body.dark-mode h2, +body.dark-mode h3, +body.dark-mode h4, +body.dark-mode h5, +body.dark-mode h6 { + color: var(--dark-mode-text-color); +} + +body.dark-mode .text-muted, +body.dark-mode .breadcrumb>.active, +body.dark-mode .help-block, +body.dark-mode .dropdown-header { + color: #999; +} + +body.dark-mode .jumbotron { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .form-control { + background-color: var(--dark-mode-input-color); + color: var(--dark-mode-text-color); + border-color: var(--dark-mode-divider); +} + +body.dark-mode .form-control:focus { + border-color: #337ab7; + box-shadow: 0 0 5px rgba(98, 0, 238, 0.5); +} + +body.dark-mode .form-control:focus { + border-color: #337ab7; + box-shadow: 0 0 5px rgba(98, 0, 238, 0.5); +} + +body.dark-mode .input-group-addon { + background-color: #444; + border-color: #444; + color: var(--dark-mode-text-color); +} + +body.dark-mode input[type="text"], +body.dark-mode input[type="file"], +body.dark-mode textarea, +body.dark-mode input[type="password"] { + background-color: var(--dark-mode-input-color); +} + +body.dark-mode .Xmce-widget, +body.dark-mode .Xmce-txt, +body.dark-mode .Xmce-ico { + color: var(--dark-mode-text-color) !important; + background-color: var(--dark-mode-primary-color) !important; + border-color: rgba(0,0,0,0) !important; +} + +body.dark-mode .Xmce-panel { + color: var(--dark-mode-text-color) !important; + background-color: var(--dark-mode-primary-color) !important; + border-color: #555 !important; +} + +body.dark-mode.Xmce-content-body { + background-color: var(--dark-mode-input-color) !important; + border-color: #555; +} + +/* Checkboxes */ +body.dark-mode input[type="checkbox"] { + color: var(--dark-mode-input-color); + background-color: var(--dark-mode-input-color); + border-color: #555; +} + +/* If you're using labels alongside checkboxes */ +body.dark-mode label { + color: var(--dark-mode-text-color); +} + +/* Hover State */ +body.dark-mode input[type="checkbox"]:hover, +body.dark-mode input[type="checkbox"]:focus { + border-color: #bb86fc; + outline: none; + /* Remove the default browser outline */ +} + +/* Checked State */ +body.dark-mode input[type="checkbox"]:checked { + background-color: #555; + border-color: #bb86fc; + /* A brighter border color for checked state */ +} + +body.dark-mode .panel { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .panel-default { + background-color: var(--dark-mode-primary-color); + border-color: var(--dark-mode-primary-color); +} + +body.dark-mode .panel-interior { + background-color: var(--dark-mode-body-color) !important; +} + +body.dark-mode .panel-default .panel-heading { + background-color: var(--dark-mode-highlight-color); + color: var(--dark-mode-text-color); + border-color: var(--dark-mode-divider); +} + +body.dark-mode .panel-default .panel-footer { + background-color: var(--dark-mode-highlight-color); + color: var(--dark-mode-text-color); + border-color: var(--dark-mode-divider); +} + +body.dark-mode .note-toolbar { + background-color: var(--dark-mode-primary-color) !important; + color: var(--dark-mode-text-color) !important; + border-color: var(--dark-mode-primary-color) !important; +} + +body.dark-mode .hashtag-btn { + color: var(--dark-mode-text-color); +} + +body.dark-mode .label { + color: var(--dark-mode-reverse-text-color); +} + +body.dark-mode .well { + background-color: #333; + border-color: #444; + color: var(--dark-mode-text-color); +} + +body.dark-mode .close { + color: var(--dark-mode-text-color); +} + +body.dark-mode .likestats { + color: var(--dark-mode-light-text-color); +} + +body.dark-mode .alert-success { + color: #d3e9d4; + background-color: #254119; + border-color: #254119; +} + +body.dark-mode .alert-info { + color: #c0e1f1; + background-color: #1b6082; + border-color: #1b6082; +} + + +body.dark-mode .alert-warning { + background-color: rgb(51, 39, 1); + border-color: rgb(51, 39, 1); + color: rgb(255, 218, 106); +} + +body.dark-mode .alert-danger { + background-color: rgb(44, 11, 14); + border-color: rgb(44, 11, 14); + color: rgb(234, 134, 143); +} + +/* Badge */ +body.dark-mode .badge { + background-color: #a5a5a5; + color: var(--dark-mode-primary-color); +} + +body.dark-mode .navbar .badge { + background-color: #a5a5a5; + color: var(--dark-mode-primary-color); +} + +body.dark-mode .navbar-default { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .navbar-default { + border-color: #000; +} + +body.dark-mode .navbar-default .navbar-nav>li>a { + color: var(--dark-mode-text-color); +} + +body.dark-mode .navbar-default .navbar-nav>li>a:hover, +body.dark-mode .navbar-default .navbar-nav>li>a:focus { + color: var(--dark-mode-text-color); + background-color: #555; +} + +body.dark-mode ul, +body.dark-mode ol { + color: var(--dark-mode-text-color); +} + +body.dark-mode li { + border-color: var(--dark-mode-divider); +} + +/* List Groups */ +body.dark-mode .list-group-item { + color: var(--dark-mode-text-color); + background-color: var(--dark-mode-body-color); + border: 1px solid var(--dark-mode-highlight-color); +} + +body.dark-mode .list-group-item.active, +body.dark-mode .list-group-item.active:hover, +body.dark-mode .list-group-item.active:focus { + /*color: var(--dark-mode-text-color);*/ + color: #ffffff; + background-color: #337ab7; + border-color: #5393d1; +} + + +body.dark-mode .list-group-item.sidebar-section:hover { + background-color: var(--dark-mode-primary-color) !important; +} + +body.dark-mode .sidebar-divider-padding { + background-color: var(--dark-mode-body-color); +} + +body.dark-mode .sidebar-item-divider { + background-color: var(--dark-mode-highlight-color); +} + +body.dark-mode .sidebar-item-smalldivider { + background-color: var(--dark-mode-highlight-color); +} + +/* If using list group with links */ +body.dark-mode .list-group-item:hover { + background-color: var(--dark-mode-highlight-color); +} + +body.dark-mode .list-group-item-heading { + color: var(--dark-mode-text-color); + /* Making headings more prominent */ +} + +body.dark-mode .list-group-item-text { + color: #b0b0b0; + /* Slightly muted text */ +} + +body.dark-mode a.list-group-item { + color: rgb(224, 224, 224); +} + + +body.dark-mode th { + font-weight: 300; +} + +/* + a.list-group-item:hover, + a.list-group-item:focus { + color: rgb(85, 85, 85); + } +*/ + +body.dark-mode .scrollbar::-webkit-scrollbar-thumb { + background-color: var(--dark-mode-divider) +} + +/* Pagination */ +body.dark-mode .pagination>li>a, +body.dark-mode .pagination>li>span { + color: var(--dark-mode-text-color); + background-color: var(--dark-mode-primary-color); + border: 1px solid var(--dark-mode-highlight-color); +} + +body.dark-mode .pagination>li>a:hover, +body.dark-mode .pagination>li>span:hover { + color: var(--dark-mode-text-color); + background-color: var(--dark-mode-highlight-color); + border-color: #444; +} + +body.dark-mode .pagination>.active>a, +body.dark-mode .pagination>.active>span, +body.dark-mode .pagination>.active>a:hover, +body.dark-mode .pagination>.active>span:hover, +body.dark-mode .pagination>.active>a:focus, +body.dark-mode .pagination>.active>span:focus { + color: var(--dark-mode-text-color); + background-color: #337ab7; + border-color: #5393d1; +} + +body.dark-mode .pagination>.disabled>span, +body.dark-mode .pagination>.disabled>span:hover, +body.dark-mode .pagination>.disabled>a, +body.dark-mode .pagination>.disabled>a:hover, +body.dark-mode .pagination>.disabled>a:focus { + color: #999999; + background-color: var(--dark-mode-primary-color); + border-color: var(--dark-mode-divider); + cursor: not-allowed; +} + +body.dark-mode .label>a, +body.dark-mode .label>a:hover { + color: var(--dark-mode-text-color); +} + + +/* Breadcrumbs */ +body.dark-mode .breadcrumb { + background-color: var(--dark-mode-primary-color); + color: var(--dark-mode-text-color); +} + +body.dark-mode .breadcrumb>li+li:before { + color: #999999; +} + +body.dark-mode a.button-link { + color: #999999 !important; +} + +body.dark-mode .table { + background-color: var(--dark-mode-primary-color); + border-color: var(--dark-mode-divider); +} + +body.dark-mode thead { + background-color: var(--dark-mode-highlight-color); +} +/* +body.dark-mode tr:hover { + background-color: var(--dark-mode-highlight-color); +} +*/ +/* Striped Table Rows */ +body.dark-mode .table-striped>tbody>tr:nth-of-type(odd) { + background-color: var(--dark-mode-primary-color); + /* Darker stripe for odd rows */ +} + +body.dark-mode .table-striped>tbody>tr:nth-of-type(even) { + background-color: var(--dark-mode-highlight-color); + /* Lighter stripe for even rows */ +} + +body.dark-mode .table th, +body.dark-mode .table td { + border-color: var(--dark-mode-divider); +} +body.dark-mode .table-bordered { + border: 0px; +} + +/* Target the first th of thead for top-left corner */ +body.dark-mode .table thead th:first-child { + border-top-left-radius: 4px; + /* Adjust this value as needed */ +} + +/* Target the last th of thead for top-right corner */ +body.dark-mode .table thead th:last-child { + border-top-right-radius: 4px; + /* Adjust this value as needed */ +} + +/* Step 1: Style the elements of the first row of every table */ +body.dark-mode .table>tbody>tr:first-child>td { + border-radius: 4px; + border-top-width: 0px; +} + +/* Step 2: Override that style for tables with a */ +body.dark-mode .table>thead+tbody>tr:first-child>td { + border-topXX: 0px; +} + + +body.dark-mode .table>thead>tr>th, +body.dark-mode .table>thead>tr>td { + border-bottom-width: 0px; + border-color: #666; + /* Making header borders slightly brighter */ +} + + +/* Default Button */ +body.dark-mode .btn-default { + background-color: #444; + border-color: #444; + color: var(--dark-mode-text-color); +} + +body.dark-mode .btn-default:hover, +body.dark-mode .btn-default:focus, +body.dark-mode .btn-default:active { + background-color: #555; + border-color: #444; +} + +/* Primary Button */ +body.dark-mode .btn-primary { + background-color: #337ab7; + border-color: #337ab7; + color: var(--dark-mode-text-color); +} + +body.dark-mode .btn-primary:hover, +body.dark-mode .btn-primary:focus, +body.dark-mode .btn-primary:active { + background-color: #5393d1; + border-color: #5393d1; +} + +/* Success Button */ +body.dark-mode .btn-success { + background-color: #388e3c; + border-color: #2e7d32; + color: var(--dark-mode-text-color); +} + +body.dark-mode .btn-success:hover, +body.dark-mode .btn-success:focus, +body.dark-mode .btn-success:active { + background-color: #2e7d32; + border-color: #1b5e20; +} + +/* Info Button */ +body.dark-mode .btn-info { + color: var(--dark-mode-reverse-text-color); + background-color: #3da8c0; + border-color: #3da8c0; +} + +body.dark-mode .btn-info:hover, +body.dark-mode .btn-info:focus, +body.dark-mode .btn-info:active { + background-color: #308a9e; + border-color: #308a9e; +} + +/* Warning Button */ +body.dark-mode .btn-warning { + background-color: rgb(245, 128, 62); + border-color: rgb(245, 128, 62); + color: var(--dark-mode-reverse-text-color); +} + +body.dark-mode .btn-warning:hover, +body.dark-mode .btn-warning:focus, +body.dark-mode .btn-warning:active { + background-color: rgb(245, 128, 62); + border-color: rgb(245, 128, 62); +} + +/* Danger Button */ +body.dark-mode .btn-danger { + background-color: #d32f2f; + border-color: #c62828; + color: var(--dark-mode-text-color); +} + +body.dark-mode .btn-danger:hover, +body.dark-mode .btn-danger:focus, +body.dark-mode .btn-danger:active { + background-color: #c62828; + border-color: #b71c1c; +} + +/* Dropdown Menus */ +body.dark-mode .dropdown-menu { + background-color: var(--dark-mode-primary-color); + border-color: var(--dark-mode-divider); +} + +body.dark-mode .dropdown-menu>li>a { + color: var(--dark-mode-text-color); +} + +body.dark-mode .dropdown-menu>li>a:hover, +body.dark-mode .dropdown-menu>li>a:focus { + color: var(--dark-mode-text-color); + background-color: var(--dark-mode-highlight-color); +} + +body.dark-mode .dropdown-menu>.active>a, +body.dark-mode .dropdown-menu>.active>a:hover, +body.dark-mode .dropdown-menu>.active>a:focus { + color: var(--dark-mode-text-color); + background-color: #6200ee; +} + +body.dark-mode .dropdown-menu>.disabled>a, +body.dark-mode .dropdown-menu>.disabled>a:hover, +body.dark-mode .dropdown-menu>.disabled>a:focus { + color: #999999; + background-color: transparent; +} + +body.dark-mode .divider { + background-color: #444; +} + +body.dark-mode .modal-content { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .modal-header { + background-color: var(--dark-mode-highlight-color); + border-color: var(--dark-mode-divider); +} + +body.dark-mode .modal-footer { + background-color: var(--dark-mode-primary-color); + border-color: var(--dark-mode-divider); +} + +body.dark-mode .chat-form { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .chat-message.received .chat-message-content, +body.dark-mode .chat-message.date .chat-message-content, +body.dark-mode .chat-timestamp-received, +body.dark-mode .chat-emoji-box { + background-color: rgb(200, 200, 200); + color: #333; +} +/* +body.dark-mode .chat-message.sent .chat-message-content { + background-color: rgb(5, 133, 148); + color: #333; +} +*/ +body.dark-mode #chat-unread-counter i { + color: rgb(200, 200, 200) !important; +} + +body.dark-mode .expanded-message { + border-style: none; +} + +body.dark-mode .dropdown-menu { + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .5); + box-shadow: 0 6px 12px rgba(0, 0, 0, .5); +} + +body.dark-mode .modal-header { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +body.dark-mode .modal-footer { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +body.dark-mode .mobilebadge { + background-color: #d43f3a !important; + border: 0px; +} + +body.dark-mode .drawer__wrapper { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .thumbnail { + border: 0px; + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .alert-gray { + color: var(--dark-mode-text-color); + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .autocomplete-list-item:not(.no-hover):hover { + color: var(--dark-mode-text-color); +} +body.dark-mode .thread-attribution { + color: var(--dark-mode-light-text-color); +} + +body.dark-mode .hashtag-box-white { + background-color: var(--dark-mode-primary-color) !important; +} + +body.dark-mode .flatpickr-calendar * { + color: var(--dark-mode-text-color) !important; + fill: var(--dark-mode-text-color) !important; + background-color: var(--dark-mode-primary-color) !important; +} + +body.dark-mode .popover { + background-color: var(--dark-mode-primary-color) !important; + border-bottom-color: var(--dark-mode-primary-color) !important; + border: 1px solid var(--dark-mode-primary-color) !important +} + +body.dark-mode .popover-title { + background-color: var(--dark-mode-primary-color) !important; +} + +body.dark-mode .popover.bottom>.arrow:after { + border-bottom-color: var(--dark-mode-primary-color) !important; +} + +body.dark-mode .popover.top>.arrow:after { + border-top-color: var(--dark-mode-primary-color) !important; +} + +body.dark-mode .fc-list-event:hover * { + background-color: var(--dark-mode-body-color) !important; +} + +body.dark-mode .list-group-item-nohover:hover { + background-color: var(--dark-mode-body-color) !important; +} + +body.dark-mode .table-hover>tbody>tr:hover { + background-color: var(--dark-mode-body-color) !important; +} + +body.dark-mode .Xmce-btn.Xmce-active * { + background-color: var(--dark-mode-highlight-color) !important; +} + +body.dark-mode .subject { + font-weight: 400; +} + +body.dark-mode a.showvisited:visited { + /* visited link */ + color: #999999; +} + +body.dark-mode .select2-selection { + background-color: var(--dark-mode-primary-color) !important; + border-color: var(--dark-mode-divider); +} + +body.dark-mode .select2-dropdown * { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .select2-selection * { + color: var(--dark-mode-text-color) !important; +} + +body.dark-mode .select2-search__field { + border: 1px solid var(--dark-mode-divider) !important; +} + +body.dark-mode .select2-dropdown { + border: 1px solid var(--dark-mode-divider) !important; +} + +body.dark-mode .select2-results__options::-webkit-scrollbar, +body.dark-mode .autocompleteResults::-webkit-scrollbar { + /*-webkit-appearance: none;*/ + width: 6px; + height: 6px; + background-color: rgba(0, 0, 0, 0); +} + +body.dark-mode .select2-results__options::-webkit-scrollbar-thumb, +body.dark-mode .autocompleteResults::-webkit-scrollbar-thumb { + border-radius: 3px; + background-color: #ccc; +} + +/* +body.dark-mode .select2-selection__rendered:focus-visible { + outline:unset; +} +*/ + +body.dark-mode .user-content a span[style*="color"] { + color: #7da8d4 !important; +} +body.dark-mode .user-content *[style*="color"], +/* This works "color" and "background-color" properties */ +body.dark-mode .user-content *[style*="background"], +/* This gets the "background" property */ +body.dark-mode .user-content *[style*="COLOR"], +/* Style entries can be case sensitive. Some old messages use caps */ +body.dark-mode .user-content font { +/* HTML 4 tag used by a few older mssgs. It has different syntax */ + color: var(--dark-mode-text-color) !important; + /* For the selectors above, set all the text to the standard color */ + background-color: transparent !important; + /* and remove backgrounds so the Groups.io bkg shows through */ +} + +body.dark-mode .user-content a span { +/* User code typically adjusts link colors by putting a span inside an anchor tag */ + color: #7da8d4 !important; + background-color: transparent !important; +} + +body.dark-mode .toc li:before { + color: var(--dark-mode-text-color); +} + +body.dark-mode .attachment-box, +body.dark-mode .attachment-box:hover { + background-color: var(--dark-mode-primary-color); +} + +body.dark-mode .attachment-name, +body.dark-mode .attachment-name-hover { + background-color: var(--dark-mode-highlight-color); +} + +body.dark-mode .attachment-box:hover .attachment-icon, +body.dark-mode .attachment-box:hover .attachment-image { + opacity: unset; +} diff --git a/groups.io/g/MTFHRT/wiki/29602.html b/groups.io/g/MTFHRT/wiki/29602.html index b8b9a11f..6f38d904 100644 --- a/groups.io/g/MTFHRT/wiki/29602.html +++ b/groups.io/g/MTFHRT/wiki/29602.html @@ -6,7 +6,7 @@ - + @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774008.1713918438252779141"); + console.log("client_id:", "web.web08.236998.1714523377861077661"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774008.1713918438252779141" + client_id: "web.web08.236998.1714523377861077661" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { - + - - + + @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="30846.html"> + Home + </a> + </li> + + <li> + <a href="32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="29602/history.html"> - 265 revisions + 266 revisions </a>    <a href="29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -672,7 +1043,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919038&Signature=QzwdmdhXhABqHW%2F6ZcCUrnRvnYk%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523977&Signature=EQRRuU0iTM6vkjRNxk2QvLVmuf4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -688,10 +1059,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Hormone powders are sold not sterile, so any cleaning / sterilization efforts before terminal heat sterilization are futile. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919038&Signature=3ZsD7iwOK%2FToKXM3h6Hef%2FyJtJ8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523977&Signature=OSg7CS5h53aZnatCg8nDXDLW7Dk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919038&Signature=RcmgQshZxijfJHI00WdybYAKW1g%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523977&Signature=FIJmoXN1dRQMmYQTRyMNOVWM%2Fng%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919038&Signature=urfCj%2BmSL9D%2BJYSgiqO%2F3So%2FT%2FY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523977&Signature=ssKaDZFV%2BUjH1JmsCThkHiF04io%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -787,7 +1158,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Myth: <span style="background-color: #ff99cc;">decrease estrogen dosage post-op</span>. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.</p> <p>Myth: <span style="background-color: #ff99cc;">"estrogens" increase risk of blood clots, take Aspirin to counteract that</span>. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.</p> <p>Fallacy: <span style="background-color: #ff99cc;">stop "hormones" some time before SRS or another surgery, resume only some time later</span>. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.</p> -<p>Schizophrenic delusion: <span style="background-color: #ff99cc;">Chinese companies have been known to mix Ethinyl Estradiol into their hormone powders as a cheap way to boost efficacy</span>. The only way for end-users to check efficiacy is an usual blood test for estradiol level which ignores ethinylestradiol completely. Therefore, only a schizophrenic (literally) could produce this raving.</p> +<p>Schizophrenic delusion: <span style="background-color: #ff99cc;">Chinese companies have been known to mix Ethinyl Estradiol into their hormone powders as a cheap way to boost efficacy</span>. The only way for end-users to check efficacy is an usual blood test for estradiol level which ignores ethinylestradiol completely. Therefore, only a schizophrenic (literally) could produce this raving.</p> <p>Myth: <span style="background-color: #ff99cc;">libido and erections are signs of testosterone</span>. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.</p> <p>Myth: <span style="background-color: #ff99cc;">excess estrogen is converted to testosterone</span>. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly <span style="text-decoration: underline;"><a href="https://www.genome.jp/kegg-bin/show_pathway?hsa00140" target="_blank" rel="nofollow noopener">unidirectional</a></span>.</p> <p>Myth: <span style="background-color: #ff99cc;">if you take too much estradiol then SHBG will bind it and make it unusable</span>. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.</p> @@ -812,66 +1183,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="30846.html"> - Home - </a> - </li> - - <li> - <a href="32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -881,9 +1216,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -912,48 +1245,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -968,13 +1296,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -996,7 +1328,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1017,138 +1349,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1170,6 +1508,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30843/171363 b/groups.io/g/MTFHRT/wiki/29602/165198 similarity index 100% rename from groups.io/g/MTFHRT/wiki/30843/171363 rename to groups.io/g/MTFHRT/wiki/29602/165198 diff --git a/groups.io/g/MTFHRT/wiki/29602/165198.html b/groups.io/g/MTFHRT/wiki/29602/165198.html deleted file mode 100644 index 5e38708c..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165198.html +++ /dev/null @@ -1,1163 +0,0 @@ - - - <!DOCTYPE html> - <html lang="en-US"> - <head> - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> - - <meta name="pinterest" content="nopin" /> - <meta name="pinterest" content="nohover" /> - - <meta name="3778517eb4810dfb5d143ed8f1b359b3b5a82923" content="0f56257c3db4a222e91b11bc6871c4df2e263b28" /> - <link rel="apple-touch-icon" sizes="57x57" href="https://groups.io/img/org.1/favicons/apple-icon-57x57.png"> - <link rel="apple-touch-icon" sizes="60x60" href="https://groups.io/img/org.1/favicons/apple-icon-60x60.png"> - <link rel="apple-touch-icon" sizes="72x72" href="https://groups.io/img/org.1/favicons/apple-icon-72x72.png"> - <link rel="apple-touch-icon" sizes="76x76" href="https://groups.io/img/org.1/favicons/apple-icon-76x76.png"> - <link rel="apple-touch-icon" sizes="114x114" href="https://groups.io/img/org.1/favicons/apple-icon-114x114.png"> - <link rel="apple-touch-icon" sizes="120x120" href="https://groups.io/img/org.1/favicons/apple-icon-120x120.png"> - <link rel="apple-touch-icon" sizes="144x144" href="https://groups.io/img/org.1/favicons/apple-icon-144x144.png"> - <link rel="apple-touch-icon" sizes="152x152" href="https://groups.io/img/org.1/favicons/apple-icon-152x152.png"> - <link rel="apple-touch-icon" sizes="180x180" href="https://groups.io/img/org.1/favicons/apple-icon-180x180.png"> - <link rel="icon" type="image/png" sizes="192x192" href="../../../../img/org.1/favicons/android-icon-192x192.png"> - <link rel="icon" type="image/png" sizes="32x32" href="../../../../img/org.1/favicons/favicon-32x32.png"> - <link rel="icon" type="image/png" sizes="96x96" href="../../../../img/org.1/favicons/favicon-96x96.png"> - <link rel="icon" type="image/png" sizes="16x16" href="../../../../img/org.1/favicons/favicon-16x16.png"> - <link rel="manifest" href="../../../../img/org.1/favicons/manifest.json"> - <meta name="msapplication-TileColor" content="#ffffff"> - <meta name="msapplication-TileImage" content="/ms-icon-144x144.png"> - - - - -<script> -/* stubs */ -const hapticsImpactHeavy = async () => { -}; -const hapticsImpactMedium = async () => { -}; -const hapticsImpactLight = async () => { -}; -const hapticsVibrate = async () => { -}; -const hapticsSelectionStart = async () => { -}; -const hapticsSelectionChanged = async () => { -}; -const hapticsSelectionEnd = async () => { -}; -</script> - - -<script> - - function setPullToRefresh() {} - - function gotoURL(inurl) { - window.location.href = inurl; - return; - } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); - if (isHTMX == true) { - document.body.addEventListener('htmx:afterSettle', f, {once: true}); - } else { - if (document.readyState !== 'loading') { - console.log('document is already ready, just execute code here'); - f(); - } else { - console.log('document was not ready, place code here'); - document.addEventListener('DOMContentLoaded', f, {once: true}); - } - } - } - - // stub - function logError(data, url, linenumber) { - console.log(data) - return; - } - var pushSubToken; - var ignoreErrors = false; - var lastError = ""; - - window.onerror = function(errorMessage, errorUrl, errorLine, errorColumn, errorObj) { - let column; - let stack; - if (console && console.log) { - console.log("msg:", errorMessage); - console.log("url:", errorUrl); - console.log("line:", errorLine); - if (errorColumn !== undefined && errorObj != null) { - console.log("column:", errorColumn); - column = errorColumn; - } - if (errorObj !== undefined && errorObj != null) { - console.log("stack:", errorObj.stack); - stack = errorObj.stack; - } - console.log("client_id:", "web.web09.775166.1713918461071472582"); - console.log("last_error:", lastError); - } - if (errorUrl == "" || errorUrl === null) { - errorUrl = window.location.href; - } - if (errorMessage.includes("SecurityError:") == true) { - ignoreErrors = true; - } - if (ignoreErrors == true) { - console.log("cookies, disabled, ignoring"); - lastError = errorMessage; - return; - } - jQuery.ajax({ - type: 'POST', - url: '/jsclienterror', - data: { - msg: errorMessage, - url: errorUrl, - line: errorLine, - column: column, - stack: stack, - last_error: lastError, - client_id: "web.web09.775166.1713918461071472582" - }, - success: function() { - if (console && console.log) { - console.log('JS error report successful.'); - } - lastError = errorMessage; - }, - error: function() { - if (console && console.error) { - console.error('JS error report submission failed!'); - } - lastError = errorMessage; - } - }); - return true; - } - -</script> - - - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> - <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> - <script src="../../../../js/run_prettify.js"></script> - <title> - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/POftzXoyXIWn/China-Oestradiol-17-Heptanoate-CAS-4956-37-0-Estradiol-Enanthate-Door-to-Door-Service.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and a spammer "Faithful". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer. These pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity is used only for scientific experiments on rats and such. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or strip the outer paint from an aluminium can from beer or a soft drink with nail polish remover, then cut the can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/30843/171364 b/groups.io/g/MTFHRT/wiki/29602/165219 similarity index 100% rename from groups.io/g/MTFHRT/wiki/30843/171364 rename to groups.io/g/MTFHRT/wiki/29602/165219 diff --git a/groups.io/g/MTFHRT/wiki/29602/165219.html b/groups.io/g/MTFHRT/wiki/29602/165219.html deleted file mode 100644 index de028468..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165219.html +++ /dev/null @@ -1,1163 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/POftzXoyXIWn/China-Oestradiol-17-Heptanoate-CAS-4956-37-0-Estradiol-Enanthate-Door-to-Door-Service.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and a spammer "Faithful". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer. These pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity is used only for scientific experiments on rats and such. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/30843/171365 b/groups.io/g/MTFHRT/wiki/29602/165250 similarity index 100% rename from groups.io/g/MTFHRT/wiki/30843/171365 rename to groups.io/g/MTFHRT/wiki/29602/165250 diff --git a/groups.io/g/MTFHRT/wiki/29602/165250.html b/groups.io/g/MTFHRT/wiki/29602/165250.html deleted file mode 100644 index 0f164dc6..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165250.html +++ /dev/null @@ -1,1164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/POftzXoyXIWn/China-Oestradiol-17-Heptanoate-CAS-4956-37-0-Estradiol-Enanthate-Door-to-Door-Service.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and a spammer "Faithful". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer. These pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity is used only for scientific experiments on rats and such. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/30843/171431 b/groups.io/g/MTFHRT/wiki/29602/165437 similarity index 100% rename from groups.io/g/MTFHRT/wiki/30843/171431 rename to groups.io/g/MTFHRT/wiki/29602/165437 diff --git a/groups.io/g/MTFHRT/wiki/29602/165437.html b/groups.io/g/MTFHRT/wiki/29602/165437.html deleted file mode 100644 index f57e4198..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165437.html +++ /dev/null @@ -1,1164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and a spammer "Faithful". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer. These pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity is used only for scientific experiments on rats and such. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/30843/171432 b/groups.io/g/MTFHRT/wiki/29602/165467 similarity index 100% rename from groups.io/g/MTFHRT/wiki/30843/171432 rename to groups.io/g/MTFHRT/wiki/29602/165467 diff --git a/groups.io/g/MTFHRT/wiki/29602/165467.html b/groups.io/g/MTFHRT/wiki/29602/165467.html deleted file mode 100644 index 50c3eb90..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165467.html +++ /dev/null @@ -1,1164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and a spammer "Faithful". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps this). These pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity is used only for scientific experiments on rats and such. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/32288/175560 b/groups.io/g/MTFHRT/wiki/29602/165469 similarity index 100% rename from groups.io/g/MTFHRT/wiki/32288/175560 rename to groups.io/g/MTFHRT/wiki/29602/165469 diff --git a/groups.io/g/MTFHRT/wiki/29602/165469.html b/groups.io/g/MTFHRT/wiki/29602/165469.html deleted file mode 100644 index 2995098e..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165469.html +++ /dev/null @@ -1,1164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and a spammer "Faithful". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps 1 or 2). These pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity is used only for scientific experiments on rats and such. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/34293/189320 b/groups.io/g/MTFHRT/wiki/29602/165470 similarity index 100% rename from groups.io/g/MTFHRT/wiki/34293/189320 rename to groups.io/g/MTFHRT/wiki/29602/165470 diff --git a/groups.io/g/MTFHRT/wiki/29602/165470.html b/groups.io/g/MTFHRT/wiki/29602/165470.html deleted file mode 100644 index 04fc874b..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165470.html +++ /dev/null @@ -1,1164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and a spammer "Faithful". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps 1 or 2). Vendors' pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity is used only for scientific experiments on rats and such. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/34293/189648 b/groups.io/g/MTFHRT/wiki/29602/165530 similarity index 100% rename from groups.io/g/MTFHRT/wiki/34293/189648 rename to groups.io/g/MTFHRT/wiki/29602/165530 diff --git a/groups.io/g/MTFHRT/wiki/29602/165530.html b/groups.io/g/MTFHRT/wiki/29602/165530.html deleted file mode 100644 index 211532c7..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165530.html +++ /dev/null @@ -1,1164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and a spammer "Faithful". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps 1 or 2). Vendors' pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity ("reference standard") is used only for calibration of measuring equipment and costs for example €353 for 100 mg. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/34293/201261 b/groups.io/g/MTFHRT/wiki/29602/165664 similarity index 100% rename from groups.io/g/MTFHRT/wiki/34293/201261 rename to groups.io/g/MTFHRT/wiki/29602/165664 diff --git a/groups.io/g/MTFHRT/wiki/29602/165664.html b/groups.io/g/MTFHRT/wiki/29602/165664.html deleted file mode 100644 index 391c300c..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165664.html +++ /dev/null @@ -1,1164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and spammers "Faithful" and "Luoxing". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps 1 or 2). Vendors' pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity ("reference standard") is used only for calibration of measuring equipment and costs for example €353 for 100 mg. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/34293/201262 b/groups.io/g/MTFHRT/wiki/29602/165830 similarity index 100% rename from groups.io/g/MTFHRT/wiki/34293/201262 rename to groups.io/g/MTFHRT/wiki/29602/165830 diff --git a/groups.io/g/MTFHRT/wiki/29602/165830.html b/groups.io/g/MTFHRT/wiki/29602/165830.html deleted file mode 100644 index 55caf5cd..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165830.html +++ /dev/null @@ -1,1165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

эта инструкция по-русски

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html
2) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and spammers "Faithful" and "Luoxing". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps 1 or 2). Vendors' pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity ("reference standard") is used only for calibration of measuring equipment and costs for example €353 for 100 mg. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/34293/201265 b/groups.io/g/MTFHRT/wiki/29602/165840 similarity index 100% rename from groups.io/g/MTFHRT/wiki/34293/201265 rename to groups.io/g/MTFHRT/wiki/29602/165840 diff --git a/groups.io/g/MTFHRT/wiki/29602/165840.html b/groups.io/g/MTFHRT/wiki/29602/165840.html deleted file mode 100644 index 2d952288..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165840.html +++ /dev/null @@ -1,1165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

эта инструкция по-русски

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html
2) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and spammers "Faithful" and "Luoxing". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps 1 or 2). Vendors' pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity ("reference standard") is used only for calibration of measuring equipment and costs for example €353 for 100 mg. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/29602/165842 b/groups.io/g/MTFHRT/wiki/29602/165842 new file mode 100644 index 00000000..51280cf4 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/29602/165842 @@ -0,0 +1 @@ +Too many requests, rate limited diff --git a/groups.io/g/MTFHRT/wiki/29602/165842.html b/groups.io/g/MTFHRT/wiki/29602/165842.html deleted file mode 100644 index 0077b4bb..00000000 --- a/groups.io/g/MTFHRT/wiki/29602/165842.html +++ /dev/null @@ -1,1165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MTFHRT@groups.io | Wiki - - - - - - - - - - - - - - - - - - -
- - - -
- -
-
- - - - - - - - - - -
-
- -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - -
- Last edited - - · - - 265 revisions - -    - - - -
-

-   -

-
- -
-
- - -

MtF HRT: Ultimate DIY

-

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

-

эта инструкция по-русски

-

-

Without gatekeepers

-

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

-

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

-

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

-

Be your own endocrinologist

-

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

-

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l.
In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

-

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

-

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

-

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

-

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

-

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

-

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp

-

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ Below I explain how you can cook injectable estradiol by yourself.

-

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

-

I advise everybody (not only MtF) to take a vitamins+minerals supplement like plain Centrum non-stop, all year round. If in USA then here or this. In Europe "One-a-Day" by Hungarian company "BiotechUSA" is cheaper in sports nutrition stores or Amazon.

-

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

-

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $76 (1 2 3a+3b) and is available not everywhere. In UK £89. In Australia $69. In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

-

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

-

In short: when it's about MtF HRT, doctors do not know better.

-

Cook your injectable estradiol by yourself

-

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you'll be able to buy ready-to-use vials from me after I return to Kiev - depends on the war. I have over 3300 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

-

Buy estradiol enanthate powder

-

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood. Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

-

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't.

-

Vendors I bought from:
1) https://aoksbio.en.made-in-china.com/product/gdnfPERUILkb/China-99-Purity-Oestradiol-17-Heptanoate-Powder-CAS-4956-37-0-with-Safe-Delivery-and-Good-Price.html
2) https://hbldbiotech.en.made-in-china.com/product/fdIAjtZoAGWq/China-Estradiol-Enanthate-CAS-4956-37-0-Large-Particle-or-Powder.html (later this seller was suspected to send not what ordered, so for now don't buy from them).

-

There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" and spammers "Faithful" and "Luoxing". Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol.

-

Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union.

-

Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps 1 or 2). Vendors' pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (I gave zeros instead of phone number and wrote "private person" instead of company name) and use the "Get Latest Price" link, tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity ("reference standard") is used only for calibration of measuring equipment and costs for example €353 for 100 mg. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers to communicate via Whatsapp or other messengers, don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html

-

Vendors offer several payment options, "Alipay" or "trust insurance in Alibaba" allow payment with a card and take 3% fee.

-

If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

-

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

-

Equipment

-

Necessary

-

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

-

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

-

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

-

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120

-

https://www.aliexpress.com/wholesale?SearchText=scales+0.001g+diamond
(check all pages).

-

If the scales have slots for 4 batteries then insert only 2 at any one side.

-

Optional

-

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

-

You can buy a 129°C autoclave for $130, but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature, too much can burst a vial. Bead sterilizers not suitable.

-

American "homebrewing" bodybuilders were afraid that their anabolics would be "inactivated" during heat sterilization, so they started the filtering fad: they assumed (wrong) that 0.2 μm filtering sterilizes. Filtering is not a reliable sterilization. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE hydrophobic 0.22 μm 25 mm syringe filter and a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for a 10 ml Luer Lock syringe, a wide wooden plank/board, a 6 l (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100°C after filtering!

-

Unnecessary

-

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

-

Other raw materials and expendables

-

Vials, stoppers, caps

-

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/223836409810
https://www.aliexpress.com/item/32903943374.html
https://www.aliexpress.com/item/33024594919.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15

-

https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps

-

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

-

-

Oil

-

MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

-

Preservative (optional)

-

Optionally you can add a preservative (antibacterial): benzyl alcohol. You'll use up 7 ml for 30 years. If you are in USA then smallest bottle (20 ml) is $7 on eBay. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

-

Syringes for mixing

-

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

-

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

-

Mix

-

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

-

-

Two recipes I can recommend:

-

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

-

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

-

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Pour estradiol enanthate powder onto the funnel over the center of the circle on the scales until the scales show any number between 0.500 and 0.503
If you poured too much, take excess powder off with a knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

-

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

-

If some powder fell off, use knife tip to put most of it back into the bag.

-

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

-

Measure the MCT oil with a syringe and pour into the vial.

-

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

-

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

-

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

-

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be slightly less or slightly more than 100°C. Measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

-

Sterilize

-

For sterilization put the sealed vial into a pot with tap water, boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker then use it instead of a pot, else a pot is enough!

-

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

-

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

-

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

-

Begin a new vial

-

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

-

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

-

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

-

Keep

-

Keep the powder sealed airtight in a vial or in a bag with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), in standing position. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

-

Total price

-

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

-

20 g of estradiol enanthate powder $180 + Alipay/Alibaba fee 3%
Scales $14.26
10 vials with stoppers and caps $4.45
2 oz (60 ml) of MCT oil $5.99
20 ml of benzyl alcohol (preservative) $6.75
5 syringes 10 ml (for measuring MCT oil) $2.66
100 syringes for injections $14.94

-

20 g of estradiol enanthate powder will be enough to cook 39 vials which will last you 39*10/0.223*7/365= 33 years.

-

Initial expenses 180*1.03+14.26+4.45+5.99+6.75+2.66+14.94= $235

-

Total expenses during 33 years (180*1.03+14.26+4*4.45+7*5.99+6.75+2.66+18*14.94)/(33.5*12)= $1.34 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

-

Legal

-

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

-

Inject yourself

-

Syringes for injections

-

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

-

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

-

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

-

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

-

Or you can mail-order. Depending on country: USA (or search), Canada: 1 2, UK: 1 2 3, France: 1 2 3, Netherlands: 1 2 3, Germany, Italy, Spain: 1 2, Denmark, Finland, Mexico, Australia: 1 2, NZ, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3.

-

Needle fright

-

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

-

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day. 20 g will last you 33 months instead of 33 years, $5/month.

-

Dosage

-

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

-

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

-
-

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

-
-

That's on 4 times higher estradiol dosage than I advise.

-

How to inject

-

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

-

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

-

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

-
-

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

-
-

Also, you can read Introduction in a scientific article.

-

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

-

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

-

"Monitoring" unnecessary

-

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

-

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

-

Any estradiol level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

-

Myths and what not to do

-

Above I explained about some myths and fallacies. Some more:

-

Myth: discard a vial 30 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

-

Fallacy: use separate needles for drawing and injection. It's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule, it's where the myth of "needle blunting" originates. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers.

-

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

-

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

-

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

-

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

-

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

-

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

-

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

-

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

-

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

-

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

-

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

-

If you are wondering about real progesterone:

-

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

-

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

-

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

-

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

-

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

-

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it to be done right, Do It Yourself.

-
-

Another my how-to: voice.

-

Lena

-

- - -

- -
- - - -
-
-
-
- -
- - - -

-
- - - - - - - - - - - diff --git a/groups.io/g/MTFHRT/wiki/29602/165844.html b/groups.io/g/MTFHRT/wiki/29602/165844.html index 0e69491b..f84b19af 100644 --- a/groups.io/g/MTFHRT/wiki/29602/165844.html +++ b/groups.io/g/MTFHRT/wiki/29602/165844.html @@ -6,7 +6,7 @@ - + @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775113.1713918459871122950"); + console.log("client_id:", "web.web09.237884.1714523402184520262"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775113.1713918459871122950" + client_id: "web.web09.237884.1714523402184520262" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { - + - - + + @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524002&Signature=JhsRdi9r3rBcDsQ6Oaig4hxe%2FzM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524002&Signature=2D9vcXt%2FoB%2FSjITCY7Ls1is0kYw%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524002&Signature=1wXuCeGgbmVvWcNup9fh0iv42lQ%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524002&Signature=MrjRZF1pHVdxlnyXEaReILap4s8%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/165880.html b/groups.io/g/MTFHRT/wiki/29602/165880.html index a058c2c5..f452a1f5 100644 --- a/groups.io/g/MTFHRT/wiki/29602/165880.html +++ b/groups.io/g/MTFHRT/wiki/29602/165880.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775603.1713918459773720613"); + console.log("client_id:", "web.web08.238281.1714523402077069135"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775603.1713918459773720613" + client_id: "web.web08.238281.1714523402077069135" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524002&Signature=JhsRdi9r3rBcDsQ6Oaig4hxe%2FzM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524002&Signature=2D9vcXt%2FoB%2FSjITCY7Ls1is0kYw%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524002&Signature=1wXuCeGgbmVvWcNup9fh0iv42lQ%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524002&Signature=MrjRZF1pHVdxlnyXEaReILap4s8%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/165882.html b/groups.io/g/MTFHRT/wiki/29602/165882.html index fe636c1e..48364175 100644 --- a/groups.io/g/MTFHRT/wiki/29602/165882.html +++ b/groups.io/g/MTFHRT/wiki/29602/165882.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775105.1713918459672287324"); + console.log("client_id:", "web.web08.238275.1714523401942802347"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775105.1713918459672287324" + client_id: "web.web08.238275.1714523401942802347" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/165974.html b/groups.io/g/MTFHRT/wiki/29602/165974.html index d70c1332..be43e612 100644 --- a/groups.io/g/MTFHRT/wiki/29602/165974.html +++ b/groups.io/g/MTFHRT/wiki/29602/165974.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775103.1713918459572049218"); + console.log("client_id:", "web.web09.237860.1714523401856951517"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775103.1713918459572049218" + client_id: "web.web09.237860.1714523401856951517" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/165976.html b/groups.io/g/MTFHRT/wiki/29602/165976.html index 703a3596..075528b9 100644 --- a/groups.io/g/MTFHRT/wiki/29602/165976.html +++ b/groups.io/g/MTFHRT/wiki/29602/165976.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775098.1713918459472436815"); + console.log("client_id:", "web.web08.238253.1714523401747091744"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775098.1713918459472436815" + client_id: "web.web08.238253.1714523401747091744" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/165985.html b/groups.io/g/MTFHRT/wiki/29602/165985.html index 9f948830..844aafb6 100644 --- a/groups.io/g/MTFHRT/wiki/29602/165985.html +++ b/groups.io/g/MTFHRT/wiki/29602/165985.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775093.1713918459372138927"); + console.log("client_id:", "web.web09.237847.1714523401661150855"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775093.1713918459372138927" + client_id: "web.web09.237847.1714523401661150855" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water or collecting dust if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/165986.html b/groups.io/g/MTFHRT/wiki/29602/165986.html index 1c56e8e1..fbbac529 100644 --- a/groups.io/g/MTFHRT/wiki/29602/165986.html +++ b/groups.io/g/MTFHRT/wiki/29602/165986.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775587.1713918459273655428"); + console.log("client_id:", "web.web09.237845.1714523401575339812"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775587.1713918459273655428" + client_id: "web.web09.237845.1714523401575339812" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/166032.html b/groups.io/g/MTFHRT/wiki/29602/166032.html index 3b7542ef..88175f35 100644 --- a/groups.io/g/MTFHRT/wiki/29602/166032.html +++ b/groups.io/g/MTFHRT/wiki/29602/166032.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775089.1713918459171677645"); + console.log("client_id:", "web.web09.237843.1714523401487725691"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775089.1713918459171677645" + client_id: "web.web09.237843.1714523401487725691" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/166033.html b/groups.io/g/MTFHRT/wiki/29602/166033.html index b2183b02..d8166e56 100644 --- a/groups.io/g/MTFHRT/wiki/29602/166033.html +++ b/groups.io/g/MTFHRT/wiki/29602/166033.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775581.1713918459073580149"); + console.log("client_id:", "web.web09.237834.1714523401398946915"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775581.1713918459073580149" + client_id: "web.web09.237834.1714523401398946915" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=aFg1kwo7u9xK9ndSHZ4fV9dGvd4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=xUbDkICfTwF%2BWP3N%2Frdaynhj1n4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=PQHhJW1S0DisC17wscZSdZsxs2k%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919059&Signature=w3lkX9sEyUhp%2FobJauMEuLqYxzg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/167382.html b/groups.io/g/MTFHRT/wiki/29602/167382.html index c2593c29..6273f1e8 100644 --- a/groups.io/g/MTFHRT/wiki/29602/167382.html +++ b/groups.io/g/MTFHRT/wiki/29602/167382.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775075.1713918458972162573"); + console.log("client_id:", "web.web08.238235.1714523401290378208"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775075.1713918458972162573" + client_id: "web.web08.238235.1714523401290378208" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/167697.html b/groups.io/g/MTFHRT/wiki/29602/167697.html index c56a6711..6f1e1946 100644 --- a/groups.io/g/MTFHRT/wiki/29602/167697.html +++ b/groups.io/g/MTFHRT/wiki/29602/167697.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775564.1713918458873551062"); + console.log("client_id:", "web.web09.237828.1714523401201770825"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775564.1713918458873551062" + client_id: "web.web09.237828.1714523401201770825" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/167699.html b/groups.io/g/MTFHRT/wiki/29602/167699.html index 96ce01fc..b5231898 100644 --- a/groups.io/g/MTFHRT/wiki/29602/167699.html +++ b/groups.io/g/MTFHRT/wiki/29602/167699.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775060.1713918458771571410"); + console.log("client_id:", "web.web08.238228.1714523401104871767"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775060.1713918458771571410" + client_id: "web.web08.238228.1714523401104871767" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/167700.html b/groups.io/g/MTFHRT/wiki/29602/167700.html index 7fa5aeb1..01eb8812 100644 --- a/groups.io/g/MTFHRT/wiki/29602/167700.html +++ b/groups.io/g/MTFHRT/wiki/29602/167700.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775055.1713918458672700541"); + console.log("client_id:", "web.web08.238220.1714523401010480641"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775055.1713918458672700541" + client_id: "web.web08.238220.1714523401010480641" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5vG80QSXUtJ548d1ZqFPzY4sLEY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=V7ybqb%2FfKs%2BgPCtN3z7UniU3NqU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5ozDCXz4bSI9g9P02rp2KPqtIa4%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524001&Signature=5KcigR0HTlcC5Y3ujI5G5nhuzPE%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/167779.html b/groups.io/g/MTFHRT/wiki/29602/167779.html index d8497e7b..393027de 100644 --- a/groups.io/g/MTFHRT/wiki/29602/167779.html +++ b/groups.io/g/MTFHRT/wiki/29602/167779.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775547.1713918458574152857"); + console.log("client_id:", "web.web09.237811.1714523400923588681"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775547.1713918458574152857" + client_id: "web.web09.237811.1714523400923588681" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/168088.html b/groups.io/g/MTFHRT/wiki/29602/168088.html index b2737314..c40dbf89 100644 --- a/groups.io/g/MTFHRT/wiki/29602/168088.html +++ b/groups.io/g/MTFHRT/wiki/29602/168088.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775048.1713918458471982815"); + console.log("client_id:", "web.web09.237799.1714523400835388609"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775048.1713918458471982815" + client_id: "web.web09.237799.1714523400835388609" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/168292.html b/groups.io/g/MTFHRT/wiki/29602/168292.html index 30c75581..cd5a51c7 100644 --- a/groups.io/g/MTFHRT/wiki/29602/168292.html +++ b/groups.io/g/MTFHRT/wiki/29602/168292.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775046.1713918458371398851"); + console.log("client_id:", "web.web08.238199.1714523400739884139"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775046.1713918458371398851" + client_id: "web.web08.238199.1714523400739884139" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -673,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -797,66 +1168,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -866,9 +1201,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -897,48 +1230,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -953,13 +1281,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -981,7 +1313,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1002,138 +1334,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1155,6 +1493,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/168872.html b/groups.io/g/MTFHRT/wiki/29602/168872.html index 208e64d2..73dc4ef4 100644 --- a/groups.io/g/MTFHRT/wiki/29602/168872.html +++ b/groups.io/g/MTFHRT/wiki/29602/168872.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775041.1713918458272416552"); + console.log("client_id:", "web.web09.237792.1714523400651256420"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775041.1713918458272416552" + client_id: "web.web09.237792.1714523400651256420" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -688,10 +1059,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -798,66 +1169,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -867,9 +1202,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -898,48 +1231,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -954,13 +1282,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -982,7 +1314,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1003,138 +1335,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1156,6 +1494,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/169943.html b/groups.io/g/MTFHRT/wiki/29602/169943.html index 0eb92bfc..5aa2b04a 100644 --- a/groups.io/g/MTFHRT/wiki/29602/169943.html +++ b/groups.io/g/MTFHRT/wiki/29602/169943.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775040.1713918458171500902"); + console.log("client_id:", "web.web08.238183.1714523400546672784"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775040.1713918458171500902" + client_id: "web.web08.238183.1714523400546672784" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -688,10 +1059,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -798,66 +1169,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -867,9 +1202,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -898,48 +1231,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -954,13 +1282,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -982,7 +1314,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1003,138 +1335,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1156,6 +1494,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/169996.html b/groups.io/g/MTFHRT/wiki/29602/169996.html index 90086fef..ef27f4ca 100644 --- a/groups.io/g/MTFHRT/wiki/29602/169996.html +++ b/groups.io/g/MTFHRT/wiki/29602/169996.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775036.1713918458071703395"); + console.log("client_id:", "web.web09.237774.1714523400454006518"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775036.1713918458071703395" + client_id: "web.web09.237774.1714523400454006518" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=7mV5X7aINgD0yqVdJBxzKe0GlBY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -688,10 +1059,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=GNG6peFGTuBJNP5S%2BZysHiTNElc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=Lp7TkKovOfNvD8UwiZ5AUL54WXE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919058&Signature=WEMZyumA34eMIxYsGmxUKfjzSy8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -798,66 +1169,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -867,9 +1202,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -898,48 +1231,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -954,13 +1282,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -982,7 +1314,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1003,138 +1335,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1156,6 +1494,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170001.html b/groups.io/g/MTFHRT/wiki/29602/170001.html index 24f47e7b..f684c639 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170001.html +++ b/groups.io/g/MTFHRT/wiki/29602/170001.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775525.1713918457974205968"); + console.log("client_id:", "web.web09.237762.1714523400363234211"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775525.1713918457974205968" + client_id: "web.web09.237762.1714523400363234211" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170019.html b/groups.io/g/MTFHRT/wiki/29602/170019.html index f527efa0..501dfcea 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170019.html +++ b/groups.io/g/MTFHRT/wiki/29602/170019.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775024.1713918457872020890"); + console.log("client_id:", "web.web09.237756.1714523400276670423"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775024.1713918457872020890" + client_id: "web.web09.237756.1714523400276670423" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170041.html b/groups.io/g/MTFHRT/wiki/29602/170041.html index 279f16b2..682a2a53 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170041.html +++ b/groups.io/g/MTFHRT/wiki/29602/170041.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775020.1713918457772181171"); + console.log("client_id:", "web.web09.237750.1714523400187858787"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775020.1713918457772181171" + client_id: "web.web09.237750.1714523400187858787" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170043.html b/groups.io/g/MTFHRT/wiki/29602/170043.html index 4a14050e..f0fa09f7 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170043.html +++ b/groups.io/g/MTFHRT/wiki/29602/170043.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775512.1713918457674341760"); + console.log("client_id:", "web.web08.238151.1714523400086369023"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775512.1713918457674341760" + client_id: "web.web08.238151.1714523400086369023" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170046.html b/groups.io/g/MTFHRT/wiki/29602/170046.html index a360f58b..952b4d1b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170046.html +++ b/groups.io/g/MTFHRT/wiki/29602/170046.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775012.1713918457571937874"); + console.log("client_id:", "web.web08.238146.1714523399991232100"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775012.1713918457571937874" + client_id: "web.web08.238146.1714523399991232100" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=Vz6WLddzDMA%2BqbRDDVVPHhTRVJ8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=v73lJwIPDPdgL3%2BeE%2BmF1nsRUwE%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=sx4PP3Z8PwYZz%2BMVHX3rnl29Wjc%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714524000&Signature=YxUf%2FfJFQDKWmWUI4vyPt%2Fmik8M%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170117.html b/groups.io/g/MTFHRT/wiki/29602/170117.html index ebd1d2e4..1a7cb058 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170117.html +++ b/groups.io/g/MTFHRT/wiki/29602/170117.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775503.1713918457474276183"); + console.log("client_id:", "web.web09.237736.1714523399906972776"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775503.1713918457474276183" + client_id: "web.web09.237736.1714523399906972776" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170292.html b/groups.io/g/MTFHRT/wiki/29602/170292.html index 8d4bb4b7..a010a359 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170292.html +++ b/groups.io/g/MTFHRT/wiki/29602/170292.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.775006.1713918457371344560"); + console.log("client_id:", "web.web08.238138.1714523399815635510"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.775006.1713918457371344560" + client_id: "web.web08.238138.1714523399815635510" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170474.html b/groups.io/g/MTFHRT/wiki/29602/170474.html index 4e8ec253..43f8c7cf 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170474.html +++ b/groups.io/g/MTFHRT/wiki/29602/170474.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774998.1713918457271745017"); + console.log("client_id:", "web.web09.237728.1714523399726604678"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774998.1713918457271745017" + client_id: "web.web09.237728.1714523399726604678" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170480.html b/groups.io/g/MTFHRT/wiki/29602/170480.html index 023e1f52..cf49523c 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170480.html +++ b/groups.io/g/MTFHRT/wiki/29602/170480.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775490.1713918457173923221"); + console.log("client_id:", "web.web08.238131.1714523399634883672"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775490.1713918457173923221" + client_id: "web.web08.238131.1714523399634883672" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170493.html b/groups.io/g/MTFHRT/wiki/29602/170493.html index 4f814d84..32706255 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170493.html +++ b/groups.io/g/MTFHRT/wiki/29602/170493.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774990.1713918457071663923"); + console.log("client_id:", "web.web09.237723.1714523399545344620"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774990.1713918457071663923" + client_id: "web.web09.237723.1714523399545344620" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=kNJQWe4ZpUKgg23czrVXRWBlcp8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=yZECbI5cnTc%2Fn4vwmtd8rK1k6Ik%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=iARFXuD2baaJf3brgBa7NO2X01w%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919057&Signature=B6Vgu%2FIB4m2lS5Q9oJ8%2FT48ZxIc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170570.html b/groups.io/g/MTFHRT/wiki/29602/170570.html index f896901b..8c0f20cc 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170570.html +++ b/groups.io/g/MTFHRT/wiki/29602/170570.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775482.1713918456973533712"); + console.log("client_id:", "web.web09.237718.1714523399457919343"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775482.1713918456973533712" + client_id: "web.web09.237718.1714523399457919343" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170572.html b/groups.io/g/MTFHRT/wiki/29602/170572.html index 8bf13e62..ab38b998 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170572.html +++ b/groups.io/g/MTFHRT/wiki/29602/170572.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775472.1713918456874009401"); + console.log("client_id:", "web.web08.238116.1714523399366770459"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775472.1713918456874009401" + client_id: "web.web08.238116.1714523399366770459" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170644.html b/groups.io/g/MTFHRT/wiki/29602/170644.html index a74dddc2..c0674300 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170644.html +++ b/groups.io/g/MTFHRT/wiki/29602/170644.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775469.1713918456774355671"); + console.log("client_id:", "web.web08.238110.1714523399273456819"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775469.1713918456774355671" + client_id: "web.web08.238110.1714523399273456819" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170646.html b/groups.io/g/MTFHRT/wiki/29602/170646.html index 555348c8..db9a3380 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170646.html +++ b/groups.io/g/MTFHRT/wiki/29602/170646.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774970.1713918456672403615"); + console.log("client_id:", "web.web09.237706.1714523399187721576"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774970.1713918456672403615" + client_id: "web.web09.237706.1714523399187721576" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170647.html b/groups.io/g/MTFHRT/wiki/29602/170647.html index 224d3e27..fa25f25f 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170647.html +++ b/groups.io/g/MTFHRT/wiki/29602/170647.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774967.1713918456571583496"); + console.log("client_id:", "web.web08.238107.1714523399087762348"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774967.1713918456571583496" + client_id: "web.web08.238107.1714523399087762348" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/170730.html b/groups.io/g/MTFHRT/wiki/29602/170730.html index 2fd44b65..87683608 100644 --- a/groups.io/g/MTFHRT/wiki/29602/170730.html +++ b/groups.io/g/MTFHRT/wiki/29602/170730.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775457.1713918456473671896"); + console.log("client_id:", "web.web08.238104.1714523398989870316"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775457.1713918456473671896" + client_id: "web.web08.238104.1714523398989870316" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=0ES7yDRp53llne6QA4OH4qdqTm0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=Gam6YXc2ulrEhL19iypWl%2BBvaf8%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=80gPebD6hxnyRmPM4uYh0lM5qhA%3D" class="myimg-responsive"/></p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> <h3><a name="Preservative-28optional29"></a>Preservative (optional)</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523999&Signature=f6cXTq62uCcUR4aa%2Bv12RQPmFfI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -799,66 +1170,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -868,9 +1203,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -899,48 +1232,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -955,13 +1283,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -983,7 +1315,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1004,138 +1336,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1157,6 +1495,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171102.html b/groups.io/g/MTFHRT/wiki/29602/171102.html index baeec6ca..35dfaef3 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171102.html +++ b/groups.io/g/MTFHRT/wiki/29602/171102.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774939.1713918456373270570"); + console.log("client_id:", "web.web09.237694.1714523398904114559"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774939.1713918456373270570" + client_id: "web.web09.237694.1714523398904114559" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -800,66 +1171,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -869,9 +1204,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -900,48 +1233,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -956,13 +1284,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -984,7 +1316,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1005,138 +1337,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1158,6 +1496,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171375.html b/groups.io/g/MTFHRT/wiki/29602/171375.html index 68e7d00c..b009bec0 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171375.html +++ b/groups.io/g/MTFHRT/wiki/29602/171375.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775431.1713918456274176484"); + console.log("client_id:", "web.web08.238094.1714523398808158593"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775431.1713918456274176484" + client_id: "web.web08.238094.1714523398808158593" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -800,66 +1171,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -869,9 +1204,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -900,48 +1233,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -956,13 +1284,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -984,7 +1316,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1005,138 +1337,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1158,6 +1496,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171433.html b/groups.io/g/MTFHRT/wiki/29602/171433.html index dbec4ad2..7dcbe334 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171433.html +++ b/groups.io/g/MTFHRT/wiki/29602/171433.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774931.1713918456171837537"); + console.log("client_id:", "web.web09.237690.1714523398722272869"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774931.1713918456171837537" + client_id: "web.web09.237690.1714523398722272869" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -674,7 +1045,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -689,10 +1060,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -800,66 +1171,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -869,9 +1204,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -900,48 +1233,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -956,13 +1284,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -984,7 +1316,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1005,138 +1337,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1158,6 +1496,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171603.html b/groups.io/g/MTFHRT/wiki/29602/171603.html index 0cfddd99..027ce74f 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171603.html +++ b/groups.io/g/MTFHRT/wiki/29602/171603.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775427.1713918456074609740"); + console.log("client_id:", "web.web08.238089.1714523398624548345"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775427.1713918456074609740" + client_id: "web.web08.238089.1714523398624548345" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=UG%2FVaHgLUyeuC03dKuCAiz3sTYU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=wflHQ2RBPY4u2vWyECs99KQjS00%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=gaRbKTXIcKXa0%2Fli6kSnIxOG8Ak%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919056&Signature=iY%2BluSH5WqucERo%2BhzyyVoirOyw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171634.html b/groups.io/g/MTFHRT/wiki/29602/171634.html index 62ca44c3..170319df 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171634.html +++ b/groups.io/g/MTFHRT/wiki/29602/171634.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775420.1713918455974072892"); + console.log("client_id:", "web.web08.238085.1714523398512965238"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775420.1713918455974072892" + client_id: "web.web08.238085.1714523398512965238" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171787.html b/groups.io/g/MTFHRT/wiki/29602/171787.html index c32d6e1a..2bae4bb8 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171787.html +++ b/groups.io/g/MTFHRT/wiki/29602/171787.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774922.1713918455872016608"); + console.log("client_id:", "web.web08.238071.1714523398418918443"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774922.1713918455872016608" + client_id: "web.web08.238071.1714523398418918443" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171799.html b/groups.io/g/MTFHRT/wiki/29602/171799.html index c301971f..d315e608 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171799.html +++ b/groups.io/g/MTFHRT/wiki/29602/171799.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775412.1713918455773161220"); + console.log("client_id:", "web.web09.237661.1714523398323939686"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775412.1713918455773161220" + client_id: "web.web09.237661.1714523398323939686" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171800.html b/groups.io/g/MTFHRT/wiki/29602/171800.html index a83c007d..a2851722 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171800.html +++ b/groups.io/g/MTFHRT/wiki/29602/171800.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775407.1713918455673567450"); + console.log("client_id:", "web.web08.238058.1714523398227872643"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775407.1713918455673567450" + client_id: "web.web08.238058.1714523398227872643" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171816.html b/groups.io/g/MTFHRT/wiki/29602/171816.html index b5e3d3a6..2c3cc774 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171816.html +++ b/groups.io/g/MTFHRT/wiki/29602/171816.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775405.1713918455574040060"); + console.log("client_id:", "web.web08.238051.1714523398131917535"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775405.1713918455574040060" + client_id: "web.web08.238051.1714523398131917535" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171845.html b/groups.io/g/MTFHRT/wiki/29602/171845.html index 36605ca7..080d1781 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171845.html +++ b/groups.io/g/MTFHRT/wiki/29602/171845.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774907.1713918455472108056"); + console.log("client_id:", "web.web08.238048.1714523398031561857"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774907.1713918455472108056" + client_id: "web.web08.238048.1714523398031561857" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=KjtXiAOtRxpb94bN0EbHtAQ6rQ0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=ZjJHDBvYrpCCZ6MlT0gMjPtSsjg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=jqIGgGgzKGMY6xXOVyNPdLiW4aU%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523998&Signature=%2BajznwfloYApO7PF9tVnmmyJu18%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171848.html b/groups.io/g/MTFHRT/wiki/29602/171848.html index d8ac3f54..02ce9272 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171848.html +++ b/groups.io/g/MTFHRT/wiki/29602/171848.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775402.1713918455373817892"); + console.log("client_id:", "web.web09.237635.1714523397943640728"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775402.1713918455373817892" + client_id: "web.web09.237635.1714523397943640728" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171933.html b/groups.io/g/MTFHRT/wiki/29602/171933.html index 6e53cbce..4a346c4b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171933.html +++ b/groups.io/g/MTFHRT/wiki/29602/171933.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774901.1713918455271332807"); + console.log("client_id:", "web.web08.238029.1714523397846766331"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774901.1713918455271332807" + client_id: "web.web08.238029.1714523397846766331" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/32903943374.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/32903943374.html</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171989.html b/groups.io/g/MTFHRT/wiki/29602/171989.html index 423e9659..f256dc0b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171989.html +++ b/groups.io/g/MTFHRT/wiki/29602/171989.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774891.1713918455171352327"); + console.log("client_id:", "web.web09.237623.1714523397758414577"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774891.1713918455171352327" + client_id: "web.web09.237623.1714523397758414577" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/171993.html b/groups.io/g/MTFHRT/wiki/29602/171993.html index 9042e303..d40f9e03 100644 --- a/groups.io/g/MTFHRT/wiki/29602/171993.html +++ b/groups.io/g/MTFHRT/wiki/29602/171993.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774887.1713918455072432318"); + console.log("client_id:", "web.web09.237611.1714523397661120424"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774887.1713918455072432318" + client_id: "web.web09.237611.1714523397661120424" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172034.html b/groups.io/g/MTFHRT/wiki/29602/172034.html index 4c78f95c..943d6320 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172034.html +++ b/groups.io/g/MTFHRT/wiki/29602/172034.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775380.1713918454973433547"); + console.log("client_id:", "web.web09.237594.1714523397553841881"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775380.1713918454973433547" + client_id: "web.web09.237594.1714523397553841881" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=e8hlqAWuLmfR%2B4LERivjeH5KEhw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=478ioho%2BNfCxyvDX%2BLgZyODODPY%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=PQklFCj07VkQTknR3aXLxVvppwA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919055&Signature=XbLERFvqWGFAi1OJjT3dAqMYWik%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172036.html b/groups.io/g/MTFHRT/wiki/29602/172036.html index 06335c98..abed7d64 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172036.html +++ b/groups.io/g/MTFHRT/wiki/29602/172036.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774879.1713918454872453187"); + console.log("client_id:", "web.web09.237588.1714523397447400928"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774879.1713918454872453187" + client_id: "web.web09.237588.1714523397447400928" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172154.html b/groups.io/g/MTFHRT/wiki/29602/172154.html index 7839fc04..6040c262 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172154.html +++ b/groups.io/g/MTFHRT/wiki/29602/172154.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775367.1713918454774219655"); + console.log("client_id:", "web.web08.237987.1714523397348440140"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775367.1713918454774219655" + client_id: "web.web08.237987.1714523397348440140" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <p>If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.</p> <h2><a name="Mix"></a>Mix</h2> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172157.html b/groups.io/g/MTFHRT/wiki/29602/172157.html index 084bffed..bfb1eec5 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172157.html +++ b/groups.io/g/MTFHRT/wiki/29602/172157.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774868.1713918454671404262"); + console.log("client_id:", "web.web08.237979.1714523397250355838"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774868.1713918454671404262" + client_id: "web.web08.237979.1714523397250355838" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -804,66 +1175,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -873,9 +1208,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -904,48 +1237,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -960,13 +1288,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -988,7 +1320,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1009,138 +1341,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1162,6 +1500,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172161.html b/groups.io/g/MTFHRT/wiki/29602/172161.html index 8564a624..cd8d4a79 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172161.html +++ b/groups.io/g/MTFHRT/wiki/29602/172161.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774863.1713918454572032055"); + console.log("client_id:", "web.web08.237972.1714523397157196239"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774863.1713918454572032055" + client_id: "web.web08.237972.1714523397157196239" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -804,66 +1175,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -873,9 +1208,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -904,48 +1237,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -960,13 +1288,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -988,7 +1320,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1009,138 +1341,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1162,6 +1500,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172176.html b/groups.io/g/MTFHRT/wiki/29602/172176.html index 7547dfb2..f57ad6e4 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172176.html +++ b/groups.io/g/MTFHRT/wiki/29602/172176.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774855.1713918454471868539"); + console.log("client_id:", "web.web08.237963.1714523397039613379"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774855.1713918454471868539" + client_id: "web.web08.237963.1714523397039613379" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=kS2wekS1zIhVBBBfSwCAbdTIpE4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=SUbG%2BP8TcY9MDo5Py4EfjNVuxuQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=lvfpM6wJsiOZ4nD9TsD9tBkcPLQ%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523997&Signature=RfLfyQHcm403fSRYE85PWlCuIHg%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -805,66 +1176,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -874,9 +1209,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -905,48 +1238,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -961,13 +1289,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -989,7 +1321,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1010,138 +1342,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1163,6 +1501,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172555.html b/groups.io/g/MTFHRT/wiki/29602/172555.html index bbeafa3a..f3d99e00 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172555.html +++ b/groups.io/g/MTFHRT/wiki/29602/172555.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775345.1713918454373668718"); + console.log("client_id:", "web.web09.237558.1714523396946250174"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775345.1713918454373668718" + client_id: "web.web09.237558.1714523396946250174" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -805,66 +1176,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -874,9 +1209,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -905,48 +1238,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -961,13 +1289,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -989,7 +1321,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1010,138 +1342,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1163,6 +1501,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172560.html b/groups.io/g/MTFHRT/wiki/29602/172560.html index e6c34cf7..915c42a7 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172560.html +++ b/groups.io/g/MTFHRT/wiki/29602/172560.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775341.1713918454273610024"); + console.log("client_id:", "web.web08.237954.1714523396846849747"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775341.1713918454273610024" + client_id: "web.web08.237954.1714523396846849747" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -805,66 +1176,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -874,9 +1209,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -905,48 +1238,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -961,13 +1289,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -989,7 +1321,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1010,138 +1342,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1163,6 +1501,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172567.html b/groups.io/g/MTFHRT/wiki/29602/172567.html index 07a2fcea..8a4d8d75 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172567.html +++ b/groups.io/g/MTFHRT/wiki/29602/172567.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775336.1713918454173637370"); + console.log("client_id:", "web.web08.237946.1714523396749356268"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775336.1713918454173637370" + client_id: "web.web08.237946.1714523396749356268" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -805,66 +1176,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -874,9 +1209,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -905,48 +1238,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -961,13 +1289,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -989,7 +1321,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1010,138 +1342,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1163,6 +1501,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172748.html b/groups.io/g/MTFHRT/wiki/29602/172748.html index b57f92d1..670eca5d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172748.html +++ b/groups.io/g/MTFHRT/wiki/29602/172748.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774835.1713918454071602550"); + console.log("client_id:", "web.web08.237941.1714523396650350489"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774835.1713918454071602550" + client_id: "web.web08.237941.1714523396650350489" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=fDS%2F1rphD7cTXWkuTbIEuurnEdE%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=4taH2TCiDPCtUAQwXoH%2FbJb6BUo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=LY3LY4A0B4HIcNNcMLD9CIFZ4QY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919054&Signature=mn3wqCEtEtZNKEmlqk7wfrfkdMw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -805,66 +1176,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -874,9 +1209,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -905,48 +1238,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -961,13 +1289,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -989,7 +1321,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1010,138 +1342,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1163,6 +1501,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/172772.html b/groups.io/g/MTFHRT/wiki/29602/172772.html index be0335bd..31d060c8 100644 --- a/groups.io/g/MTFHRT/wiki/29602/172772.html +++ b/groups.io/g/MTFHRT/wiki/29602/172772.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775323.1713918453973516943"); + console.log("client_id:", "web.web09.237533.1714523396560756408"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775323.1713918453973516943" + client_id: "web.web09.237533.1714523396560756408" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -805,66 +1176,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -874,9 +1209,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -905,48 +1238,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -961,13 +1289,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -989,7 +1321,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1010,138 +1342,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1163,6 +1501,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173017.html b/groups.io/g/MTFHRT/wiki/29602/173017.html index c7e137e3..a51784ac 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173017.html +++ b/groups.io/g/MTFHRT/wiki/29602/173017.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775318.1713918453873317059"); + console.log("client_id:", "web.web08.237930.1714523396456079517"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775318.1713918453873317059" + client_id: "web.web08.237930.1714523396456079517" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173018.html b/groups.io/g/MTFHRT/wiki/29602/173018.html index 8f2fd83d..0d90addb 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173018.html +++ b/groups.io/g/MTFHRT/wiki/29602/173018.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774817.1713918453771288070"); + console.log("client_id:", "web.web09.237518.1714523396363617979"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774817.1713918453771288070" + client_id: "web.web09.237518.1714523396363617979" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173019.html b/groups.io/g/MTFHRT/wiki/29602/173019.html index 4a70bfb4..9a42b140 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173019.html +++ b/groups.io/g/MTFHRT/wiki/29602/173019.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775305.1713918453674063907"); + console.log("client_id:", "web.web08.237917.1714523396270217613"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775305.1713918453674063907" + client_id: "web.web08.237917.1714523396270217613" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173224.html b/groups.io/g/MTFHRT/wiki/29602/173224.html index 727faf63..9cfb2e9e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173224.html +++ b/groups.io/g/MTFHRT/wiki/29602/173224.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775301.1713918453573994064"); + console.log("client_id:", "web.web09.237511.1714523396179504143"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775301.1713918453573994064" + client_id: "web.web09.237511.1714523396179504143" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173225.html b/groups.io/g/MTFHRT/wiki/29602/173225.html index caa2f0f4..09a78c1b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173225.html +++ b/groups.io/g/MTFHRT/wiki/29602/173225.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775294.1713918453474182952"); + console.log("client_id:", "web.web08.237912.1714523396085618490"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775294.1713918453474182952" + client_id: "web.web08.237912.1714523396085618490" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173240.html b/groups.io/g/MTFHRT/wiki/29602/173240.html index 5784d255..1669c105 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173240.html +++ b/groups.io/g/MTFHRT/wiki/29602/173240.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774793.1713918453371798046"); + console.log("client_id:", "web.web09.237502.1714523395998390377"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774793.1713918453371798046" + client_id: "web.web09.237502.1714523395998390377" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=efzaTvvUl6HnS20Qancpl22lviM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=iauri9PV%2FFs8ZuS%2BNYhe%2BtgeCpU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=ftI57CKXudd9V9w7kcJ6JKSVtoY%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523996&Signature=%2BD%2BQQ%2B3QVpXS9JWLwYCqnBpyOQc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173241.html b/groups.io/g/MTFHRT/wiki/29602/173241.html index de433df5..7af9728d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173241.html +++ b/groups.io/g/MTFHRT/wiki/29602/173241.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774790.1713918453271437080"); + console.log("client_id:", "web.web09.237494.1714523395906877925"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774790.1713918453271437080" + client_id: "web.web09.237494.1714523395906877925" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173242.html b/groups.io/g/MTFHRT/wiki/29602/173242.html index f18cbdac..992e4e5e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173242.html +++ b/groups.io/g/MTFHRT/wiki/29602/173242.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775285.1713918453174333653"); + console.log("client_id:", "web.web09.237489.1714523395819653152"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775285.1713918453174333653" + client_id: "web.web09.237489.1714523395819653152" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173359.html b/groups.io/g/MTFHRT/wiki/29602/173359.html index 493417f0..075c8734 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173359.html +++ b/groups.io/g/MTFHRT/wiki/29602/173359.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774786.1713918453071883686"); + console.log("client_id:", "web.web08.237884.1714523395713876834"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774786.1713918453071883686" + client_id: "web.web08.237884.1714523395713876834" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XE7VV%2FL6fPwPNNPS0P%2Fw8i5zoLM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=YznhalUHzkTQKT9epR9JW9%2FM80E%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=ME%2FoIETNY4AhDMy58lTLEEZH%2BAk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919053&Signature=XdUwOHvqLYZyCrMHm%2BqnhZdok18%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173385.html b/groups.io/g/MTFHRT/wiki/29602/173385.html index 4cfee96c..3f2fc3e6 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173385.html +++ b/groups.io/g/MTFHRT/wiki/29602/173385.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775280.1713918452974215667"); + console.log("client_id:", "web.web09.237473.1714523395624824001"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775280.1713918452974215667" + client_id: "web.web09.237473.1714523395624824001" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173450.html b/groups.io/g/MTFHRT/wiki/29602/173450.html index 6f9c84b4..ce196c2e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173450.html +++ b/groups.io/g/MTFHRT/wiki/29602/173450.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775277.1713918452873488918"); + console.log("client_id:", "web.web08.237870.1714523395529676173"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775277.1713918452873488918" + client_id: "web.web08.237870.1714523395529676173" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173566.html b/groups.io/g/MTFHRT/wiki/29602/173566.html index 4245187b..6d8ec179 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173566.html +++ b/groups.io/g/MTFHRT/wiki/29602/173566.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775271.1713918452774238300"); + console.log("client_id:", "web.web09.237456.1714523395438682002"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775271.1713918452774238300" + client_id: "web.web09.237456.1714523395438682002" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173659.html b/groups.io/g/MTFHRT/wiki/29602/173659.html index 42189481..78c95608 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173659.html +++ b/groups.io/g/MTFHRT/wiki/29602/173659.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774768.1713918452672211378"); + console.log("client_id:", "web.web08.237856.1714523395337039561"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774768.1713918452672211378" + client_id: "web.web08.237856.1714523395337039561" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173669.html b/groups.io/g/MTFHRT/wiki/29602/173669.html index 2ed29501..6e66b24c 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173669.html +++ b/groups.io/g/MTFHRT/wiki/29602/173669.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774759.1713918452572933481"); + console.log("client_id:", "web.web09.237450.1714523395247906195"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774759.1713918452572933481" + client_id: "web.web09.237450.1714523395247906195" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173845.html b/groups.io/g/MTFHRT/wiki/29602/173845.html index 8bf98d0f..0f6bf7c9 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173845.html +++ b/groups.io/g/MTFHRT/wiki/29602/173845.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775254.1713918452473708397"); + console.log("client_id:", "web.web08.237840.1714523395153187443"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775254.1713918452473708397" + client_id: "web.web08.237840.1714523395153187443" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/173933.html b/groups.io/g/MTFHRT/wiki/29602/173933.html index 2baa867c..a318404b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/173933.html +++ b/groups.io/g/MTFHRT/wiki/29602/173933.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774753.1713918452371375366"); + console.log("client_id:", "web.web09.237431.1714523395063818218"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774753.1713918452371375366" + client_id: "web.web09.237431.1714523395063818218" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=ecRlTufT8XcFINksEE0BTRvAjg0%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=dX6VIlGUhzEpSCorx6Jbpkk%2FArs%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=0Q9Vn%2BA%2FxrKzYT%2B2eq3iwvraTao%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523995&Signature=pF7q6%2BNVFC%2F1PTX3LVkaGxQCehY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/174038.html b/groups.io/g/MTFHRT/wiki/29602/174038.html index a0770f11..5aea9aa2 100644 --- a/groups.io/g/MTFHRT/wiki/29602/174038.html +++ b/groups.io/g/MTFHRT/wiki/29602/174038.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775245.1713918452273992803"); + console.log("client_id:", "web.web09.237427.1714523394976240777"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775245.1713918452273992803" + client_id: "web.web09.237427.1714523394976240777" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/174146.html b/groups.io/g/MTFHRT/wiki/29602/174146.html index eb0c65e8..98ec038f 100644 --- a/groups.io/g/MTFHRT/wiki/29602/174146.html +++ b/groups.io/g/MTFHRT/wiki/29602/174146.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775242.1713918452173747687"); + console.log("client_id:", "web.web08.237819.1714523394878662523"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775242.1713918452173747687" + client_id: "web.web08.237819.1714523394878662523" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -675,7 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -690,10 +1061,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -705,7 +1076,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175306.html b/groups.io/g/MTFHRT/wiki/29602/175306.html index 57b525d1..9b8e7ac1 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175306.html +++ b/groups.io/g/MTFHRT/wiki/29602/175306.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774737.1713918452071401423"); + console.log("client_id:", "web.web09.237415.1714523394788742610"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774737.1713918452071401423" + client_id: "web.web09.237415.1714523394788742610" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=uRTSVG%2FDVeClmegV8SnfXqqDRwM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=lfqHRv7MOBfTUKhPIisiKoI%2BauQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=gZiuB3xPZ3J%2Fbzr98B%2BJPfQzC5I%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919052&Signature=4NRXq8jBkBXWxp%2Bw8kTLNTo8Wco%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -801,66 +1172,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -870,9 +1205,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -901,48 +1234,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -957,13 +1285,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -985,7 +1317,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1006,138 +1338,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1159,6 +1497,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175308.html b/groups.io/g/MTFHRT/wiki/29602/175308.html index 576bcd01..41288b89 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175308.html +++ b/groups.io/g/MTFHRT/wiki/29602/175308.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774735.1713918451971490534"); + console.log("client_id:", "web.web08.237813.1714523394695952742"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774735.1713918451971490534" + client_id: "web.web08.237813.1714523394695952742" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175309.html b/groups.io/g/MTFHRT/wiki/29602/175309.html index d6102f4c..377f8fa9 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175309.html +++ b/groups.io/g/MTFHRT/wiki/29602/175309.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775219.1713918451873967409"); + console.log("client_id:", "web.web09.237405.1714523394606180954"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775219.1713918451873967409" + client_id: "web.web09.237405.1714523394606180954" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175312.html b/groups.io/g/MTFHRT/wiki/29602/175312.html index faa3d421..dd6f010a 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175312.html +++ b/groups.io/g/MTFHRT/wiki/29602/175312.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775215.1713918451773795985"); + console.log("client_id:", "web.web08.237804.1714523394508513498"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775215.1713918451773795985" + client_id: "web.web08.237804.1714523394508513498" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175559.html b/groups.io/g/MTFHRT/wiki/29602/175559.html index 7a971810..f81de4aa 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175559.html +++ b/groups.io/g/MTFHRT/wiki/29602/175559.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775212.1713918451674569737"); + console.log("client_id:", "web.web08.237798.1714523394413603738"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775212.1713918451674569737" + client_id: "web.web08.237798.1714523394413603738" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175562.html b/groups.io/g/MTFHRT/wiki/29602/175562.html index 5c2b973f..e3e2d18a 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175562.html +++ b/groups.io/g/MTFHRT/wiki/29602/175562.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775209.1713918451574359432"); + console.log("client_id:", "web.web09.237392.1714523394326263754"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775209.1713918451574359432" + client_id: "web.web09.237392.1714523394326263754" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175563.html b/groups.io/g/MTFHRT/wiki/29602/175563.html index ba3ff6de..748b115b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175563.html +++ b/groups.io/g/MTFHRT/wiki/29602/175563.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775205.1713918451474804722"); + console.log("client_id:", "web.web08.237791.1714523394230564565"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775205.1713918451474804722" + client_id: "web.web08.237791.1714523394230564565" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175671.html b/groups.io/g/MTFHRT/wiki/29602/175671.html index 1f622583..e16e155b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175671.html +++ b/groups.io/g/MTFHRT/wiki/29602/175671.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774706.1713918451371673272"); + console.log("client_id:", "web.web09.237386.1714523394141073475"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774706.1713918451371673272" + client_id: "web.web09.237386.1714523394141073475" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175689.html b/groups.io/g/MTFHRT/wiki/29602/175689.html index cea7b864..ec90fdbd 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175689.html +++ b/groups.io/g/MTFHRT/wiki/29602/175689.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775199.1713918451273594097"); + console.log("client_id:", "web.web08.237787.1714523394046478204"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775199.1713918451273594097" + client_id: "web.web08.237787.1714523394046478204" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=VgqS1kH%2FOzaCTumSl3vvZWIsSnk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=wmOKZwze27SGu5qNkUXobrW7BSU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=oFmY7LLMm4gtYmJ112Douzzq0WM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523994&Signature=D27JZakEcRq705ZhvW%2BanQwkHJA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175730.html b/groups.io/g/MTFHRT/wiki/29602/175730.html index 7349651d..a9c6088e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175730.html +++ b/groups.io/g/MTFHRT/wiki/29602/175730.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774700.1713918451171701140"); + console.log("client_id:", "web.web09.237379.1714523393957181472"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774700.1713918451171701140" + client_id: "web.web09.237379.1714523393957181472" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175908.html b/groups.io/g/MTFHRT/wiki/29602/175908.html index a7ee5021..cf1faf56 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175908.html +++ b/groups.io/g/MTFHRT/wiki/29602/175908.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775192.1713918451073988454"); + console.log("client_id:", "web.web09.237371.1714523393866665851"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775192.1713918451073988454" + client_id: "web.web09.237371.1714523393866665851" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=h%2Fkl8lOEG3JqOVJeWfjoNQKBQNA%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=lJYhr6Fvf6Mx69PZ3fUTCxQuZdo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=6EmJQkDVrDzyFA%2Bkm%2FHYDoRLBoA%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919051&Signature=MNg%2BzVC3coyh2yZwvFTJpUH7Mzk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -802,66 +1173,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -871,9 +1206,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -902,48 +1235,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -958,13 +1286,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -986,7 +1318,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1007,138 +1339,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1160,6 +1498,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175930.html b/groups.io/g/MTFHRT/wiki/29602/175930.html index dde5e306..7329f8e3 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175930.html +++ b/groups.io/g/MTFHRT/wiki/29602/175930.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775180.1713918450973528247"); + console.log("client_id:", "web.web08.237767.1714523393772764480"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775180.1713918450973528247" + client_id: "web.web08.237767.1714523393772764480" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/175991.html b/groups.io/g/MTFHRT/wiki/29602/175991.html index f7aacbce..9f045df9 100644 --- a/groups.io/g/MTFHRT/wiki/29602/175991.html +++ b/groups.io/g/MTFHRT/wiki/29602/175991.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775173.1713918450873787105"); + console.log("client_id:", "web.web08.237760.1714523393677347966"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775173.1713918450873787105" + client_id: "web.web08.237760.1714523393677347966" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176625.html b/groups.io/g/MTFHRT/wiki/29602/176625.html index 8aaf39fb..79c189b4 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176625.html +++ b/groups.io/g/MTFHRT/wiki/29602/176625.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774672.1713918450771739138"); + console.log("client_id:", "web.web08.237758.1714523393583620404"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774672.1713918450771739138" + client_id: "web.web08.237758.1714523393583620404" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176627.html b/groups.io/g/MTFHRT/wiki/29602/176627.html index ced21505..2fcd6809 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176627.html +++ b/groups.io/g/MTFHRT/wiki/29602/176627.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775167.1713918450673971989"); + console.log("client_id:", "web.web08.237750.1714523393484431323"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775167.1713918450673971989" + client_id: "web.web08.237750.1714523393484431323" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176633.html b/groups.io/g/MTFHRT/wiki/29602/176633.html index 523349eb..3c0e21e0 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176633.html +++ b/groups.io/g/MTFHRT/wiki/29602/176633.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774667.1713918450571881947"); + console.log("client_id:", "web.web09.237342.1714523393394655557"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774667.1713918450571881947" + client_id: "web.web09.237342.1714523393394655557" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176690.html b/groups.io/g/MTFHRT/wiki/29602/176690.html index e65e0544..83f478ea 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176690.html +++ b/groups.io/g/MTFHRT/wiki/29602/176690.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775160.1713918450474050663"); + console.log("client_id:", "web.web09.237339.1714523393304509642"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775160.1713918450474050663" + client_id: "web.web09.237339.1714523393304509642" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176779.html b/groups.io/g/MTFHRT/wiki/29602/176779.html index f4a9e3bc..e2076e7d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176779.html +++ b/groups.io/g/MTFHRT/wiki/29602/176779.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774659.1713918450371287892"); + console.log("client_id:", "web.web08.237739.1714523393210922131"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774659.1713918450371287892" + client_id: "web.web08.237739.1714523393210922131" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176862.html b/groups.io/g/MTFHRT/wiki/29602/176862.html index 1679a83a..f66f1ede 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176862.html +++ b/groups.io/g/MTFHRT/wiki/29602/176862.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775151.1713918450273791724"); + console.log("client_id:", "web.web09.237334.1714523393123452489"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775151.1713918450273791724" + client_id: "web.web09.237334.1714523393123452489" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176863.html b/groups.io/g/MTFHRT/wiki/29602/176863.html index a7b4cf03..86e0fe23 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176863.html +++ b/groups.io/g/MTFHRT/wiki/29602/176863.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775147.1713918450173960822"); + console.log("client_id:", "web.web08.237730.1714523393027357314"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775147.1713918450173960822" + client_id: "web.web08.237730.1714523393027357314" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=QsOXd3bmjQHpek7R9LSm0VA7a0w%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=P%2FNNawNxoY4Ql0chqb0W%2B2UA0bI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=GtyI15NgrGMl1AdraNZUs5kr1sM%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523993&Signature=NbsaorqOf6qpYtyV0lfoPGat4Lo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176870.html b/groups.io/g/MTFHRT/wiki/29602/176870.html index 3fbe7e52..720c32ff 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176870.html +++ b/groups.io/g/MTFHRT/wiki/29602/176870.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774645.1713918450071573185"); + console.log("client_id:", "web.web09.237324.1714523392937386901"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774645.1713918450071573185" + client_id: "web.web09.237324.1714523392937386901" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=xk3%2FqKqZSQ0nKr3IPrKcGygeNpw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=ir60Vn8aUep4jDChi%2Bw%2FiLu1mm0%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=wTA5gZh9ZZGwExuvutcyC%2BeW8vE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919050&Signature=11sxjUsIOzb%2FrT9mV0iZZlHMvf0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/176939.html b/groups.io/g/MTFHRT/wiki/29602/176939.html index db34125d..118bab81 100644 --- a/groups.io/g/MTFHRT/wiki/29602/176939.html +++ b/groups.io/g/MTFHRT/wiki/29602/176939.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774629.1713918449972139536"); + console.log("client_id:", "web.web08.237726.1714523392840478224"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774629.1713918449972139536" + client_id: "web.web08.237726.1714523392840478224" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/177139.html b/groups.io/g/MTFHRT/wiki/29602/177139.html index 661cb515..fb35eb95 100644 --- a/groups.io/g/MTFHRT/wiki/29602/177139.html +++ b/groups.io/g/MTFHRT/wiki/29602/177139.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775120.1713918449874167103"); + console.log("client_id:", "web.web09.237307.1714523392751090048"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775120.1713918449874167103" + client_id: "web.web09.237307.1714523392751090048" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/177140.html b/groups.io/g/MTFHRT/wiki/29602/177140.html index 8a7073a1..6764535b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/177140.html +++ b/groups.io/g/MTFHRT/wiki/29602/177140.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775114.1713918449773977489"); + console.log("client_id:", "web.web08.237704.1714523392652973190"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775114.1713918449773977489" + client_id: "web.web08.237704.1714523392652973190" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/178199.html b/groups.io/g/MTFHRT/wiki/29602/178199.html index 70769900..b7f09294 100644 --- a/groups.io/g/MTFHRT/wiki/29602/178199.html +++ b/groups.io/g/MTFHRT/wiki/29602/178199.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774611.1713918449671692473"); + console.log("client_id:", "web.web09.237297.1714523392561113838"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774611.1713918449671692473" + client_id: "web.web09.237297.1714523392561113838" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/178236.html b/groups.io/g/MTFHRT/wiki/29602/178236.html index 2bda2b63..89d7c7e0 100644 --- a/groups.io/g/MTFHRT/wiki/29602/178236.html +++ b/groups.io/g/MTFHRT/wiki/29602/178236.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775104.1713918449574066544"); + console.log("client_id:", "web.web08.237687.1714523392465772398"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775104.1713918449574066544" + client_id: "web.web08.237687.1714523392465772398" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/178516.html b/groups.io/g/MTFHRT/wiki/29602/178516.html index 13a5362c..22c71e7c 100644 --- a/groups.io/g/MTFHRT/wiki/29602/178516.html +++ b/groups.io/g/MTFHRT/wiki/29602/178516.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774599.1713918449471940776"); + console.log("client_id:", "web.web09.237276.1714523392375043589"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774599.1713918449471940776" + client_id: "web.web09.237276.1714523392375043589" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added, not "Pure C8") - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/178517.html b/groups.io/g/MTFHRT/wiki/29602/178517.html index 069ab6bb..6f836a85 100644 --- a/groups.io/g/MTFHRT/wiki/29602/178517.html +++ b/groups.io/g/MTFHRT/wiki/29602/178517.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775088.1713918449373642384"); + console.log("client_id:", "web.web09.237272.1714523392285434987"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775088.1713918449373642384" + client_id: "web.web09.237272.1714523392285434987" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/178526.html b/groups.io/g/MTFHRT/wiki/29602/178526.html index 511f9d20..13fe1c42 100644 --- a/groups.io/g/MTFHRT/wiki/29602/178526.html +++ b/groups.io/g/MTFHRT/wiki/29602/178526.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775082.1713918449274286816"); + console.log("client_id:", "web.web08.237670.1714523392180082329"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775082.1713918449274286816" + client_id: "web.web08.237670.1714523392180082329" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/179227.html b/groups.io/g/MTFHRT/wiki/29602/179227.html index 1d5c7721..e86e0563 100644 --- a/groups.io/g/MTFHRT/wiki/29602/179227.html +++ b/groups.io/g/MTFHRT/wiki/29602/179227.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774583.1713918449191253664"); + console.log("client_id:", "web.web09.237264.1714523392088758557"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774583.1713918449191253664" + client_id: "web.web09.237264.1714523392088758557" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22VIC10%20000%22" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG%20000%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/de_DE/?ObjectPath=/Shops/171448/Products/%22BKMA%20000%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%20000%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/179444.html b/groups.io/g/MTFHRT/wiki/29602/179444.html index 6372f4aa..9aa1c5c2 100644 --- a/groups.io/g/MTFHRT/wiki/29602/179444.html +++ b/groups.io/g/MTFHRT/wiki/29602/179444.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775072.1713918449107316788"); + console.log("client_id:", "web.web08.237660.1714523391987608109"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775072.1713918449107316788" + client_id: "web.web08.237660.1714523391987608109" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=R%2B7ViozGxWw0f7efMjtnT4HV49Q%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=YWk%2F%2B5Lvc%2Bf4Ywd0PTLQFHlxcrg%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=dhyg15hIpYz297iM%2F3Yf9AqjP7w%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523992&Signature=IFrUliUYGqJkBJRp3H4e3N%2Fxc48%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -803,66 +1174,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -872,9 +1207,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -903,48 +1236,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -959,13 +1287,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -987,7 +1319,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1008,138 +1340,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1161,6 +1499,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/181040.html b/groups.io/g/MTFHRT/wiki/29602/181040.html index 2a12911a..0e772196 100644 --- a/groups.io/g/MTFHRT/wiki/29602/181040.html +++ b/groups.io/g/MTFHRT/wiki/29602/181040.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774574.1713918449031170772"); + console.log("client_id:", "web.web09.237254.1714523391898035141"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774574.1713918449031170772" + client_id: "web.web09.237254.1714523391898035141" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=lne2wSO0%2BYARJ2iNCqR%2FeabBo0s%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=tjI39GkxBQSg5izxEFYJVtvHiEI%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=WTR%2BoR7G5Vq%2B7oSttprUuqcU0TM%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919049&Signature=pQTAo%2Bhg3mzhYSqS9RfT2hpSabo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -804,66 +1175,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -873,9 +1208,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -904,48 +1237,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -960,13 +1288,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -988,7 +1320,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1009,138 +1341,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1162,6 +1500,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/181092.html b/groups.io/g/MTFHRT/wiki/29602/181092.html index ccfaf870..92aee1fa 100644 --- a/groups.io/g/MTFHRT/wiki/29602/181092.html +++ b/groups.io/g/MTFHRT/wiki/29602/181092.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774569.1713918448948540761"); + console.log("client_id:", "web.web09.237247.1714523391810092083"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774569.1713918448948540761" + client_id: "web.web09.237247.1714523391810092083" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/lab-supplies/rls-10ml-molded-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://ezvialz.com/vial-samples/1149-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-pk-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://ezvialz.com/20mm-vial-stoppers/1105-20mm-round-bottom-vial-stopper-sample-pack-of-10-pieces.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://ezvialz.com/20mm-center-tear-vial-seals/978-20mm-center-tear-vial-seals-dusty-pink-pk-of-100.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -804,66 +1175,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -873,9 +1208,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -904,48 +1237,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -960,13 +1288,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -988,7 +1320,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1009,138 +1341,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1162,6 +1500,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/181266.html b/groups.io/g/MTFHRT/wiki/29602/181266.html index 04811470..77ff37e7 100644 --- a/groups.io/g/MTFHRT/wiki/29602/181266.html +++ b/groups.io/g/MTFHRT/wiki/29602/181266.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774556.1713918448876320072"); + console.log("client_id:", "web.web09.237239.1714523391716147009"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774556.1713918448876320072" + client_id: "web.web09.237239.1714523391716147009" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>.</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -804,66 +1175,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -873,9 +1208,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -904,48 +1237,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -960,13 +1288,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -988,7 +1320,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1009,138 +1341,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1162,6 +1500,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/181781.html b/groups.io/g/MTFHRT/wiki/29602/181781.html index fee62ff1..f223dd65 100644 --- a/groups.io/g/MTFHRT/wiki/29602/181781.html +++ b/groups.io/g/MTFHRT/wiki/29602/181781.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774551.1713918448801237642"); + console.log("client_id:", "web.web08.237640.1714523391610300694"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774551.1713918448801237642" + client_id: "web.web08.237640.1714523391610300694" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -804,66 +1175,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -873,9 +1208,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -904,48 +1237,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -960,13 +1288,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -988,7 +1320,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1009,138 +1341,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1162,6 +1500,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/183064.html b/groups.io/g/MTFHRT/wiki/29602/183064.html index be820c08..f7e77b70 100644 --- a/groups.io/g/MTFHRT/wiki/29602/183064.html +++ b/groups.io/g/MTFHRT/wiki/29602/183064.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775041.1713918448715255630"); + console.log("client_id:", "web.web08.237635.1714523391515680065"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775041.1713918448715255630" + client_id: "web.web08.237635.1714523391515680065" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">stoppers</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -804,66 +1175,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -873,9 +1208,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -904,48 +1237,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -960,13 +1288,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -988,7 +1320,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1009,138 +1341,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1162,6 +1500,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/184065.html b/groups.io/g/MTFHRT/wiki/29602/184065.html index 3af2eec6..11046a7c 100644 --- a/groups.io/g/MTFHRT/wiki/29602/184065.html +++ b/groups.io/g/MTFHRT/wiki/29602/184065.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775038.1713918448624312129"); + console.log("client_id:", "web.web09.237228.1714523391422507094"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775038.1713918448624312129" + client_id: "web.web09.237228.1714523391422507094" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -804,66 +1175,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -873,9 +1208,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -904,48 +1237,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -960,13 +1288,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -988,7 +1320,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1009,138 +1341,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1162,6 +1500,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/184355.html b/groups.io/g/MTFHRT/wiki/29602/184355.html index c0789300..a932c13e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/184355.html +++ b/groups.io/g/MTFHRT/wiki/29602/184355.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774538.1713918448544575062"); + console.log("client_id:", "web.web08.237628.1714523391325609773"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774538.1713918448544575062" + client_id: "web.web08.237628.1714523391325609773" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/184356.html b/groups.io/g/MTFHRT/wiki/29602/184356.html index 30d830c6..b7589a90 100644 --- a/groups.io/g/MTFHRT/wiki/29602/184356.html +++ b/groups.io/g/MTFHRT/wiki/29602/184356.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775032.1713918448457146330"); + console.log("client_id:", "web.web09.237222.1714523391234972975"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775032.1713918448457146330" + client_id: "web.web09.237222.1714523391234972975" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -805,66 +1176,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -874,9 +1209,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -905,48 +1238,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -961,13 +1289,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -989,7 +1321,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1010,138 +1342,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1163,6 +1501,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/184675.html b/groups.io/g/MTFHRT/wiki/29602/184675.html index 853932ea..5dd946d6 100644 --- a/groups.io/g/MTFHRT/wiki/29602/184675.html +++ b/groups.io/g/MTFHRT/wiki/29602/184675.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775028.1713918448370559030"); + console.log("client_id:", "web.web09.237219.1714523391144877561"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775028.1713918448370559030" + client_id: "web.web09.237219.1714523391144877561" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <h3><a name="Oil"></a>Oil</h3> <p>MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle <a href="https://www.ebay.com/sch/i.html?_nkw=mct+oil&_sacat=0&LH_BIN=1&_sop=15&_fcid=1&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on eBay</a> for $6 including shipping. Check prices also on Amazon. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).</p> @@ -700,7 +1071,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -805,66 +1176,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -874,9 +1209,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -905,48 +1238,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -961,13 +1289,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -989,7 +1321,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1010,138 +1342,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1163,6 +1501,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/184793.html b/groups.io/g/MTFHRT/wiki/29602/184793.html index 16549825..c895d4f1 100644 --- a/groups.io/g/MTFHRT/wiki/29602/184793.html +++ b/groups.io/g/MTFHRT/wiki/29602/184793.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774529.1713918448295087286"); + console.log("client_id:", "web.web08.237614.1714523391052869976"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774529.1713918448295087286" + client_id: "web.web08.237614.1714523391052869976" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=21uG706uPSNnW2w%2FxTgofzUvnN4%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=1QibDdDK7SzXujnT4H2ZLPGf37k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sp3%2BaTyM7BhrCpNvmXprXnLOcJE%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials made in USA <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523991&Signature=sg13HGNXepvZdbOpT5RRnwgWnWA%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/184817.html b/groups.io/g/MTFHRT/wiki/29602/184817.html index 93a0712d..00af75f5 100644 --- a/groups.io/g/MTFHRT/wiki/29602/184817.html +++ b/groups.io/g/MTFHRT/wiki/29602/184817.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775022.1713918448210021187"); + console.log("client_id:", "web.web09.237209.1714523390958596469"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775022.1713918448210021187" + client_id: "web.web09.237209.1714523390958596469" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials made in USA <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/185552.html b/groups.io/g/MTFHRT/wiki/29602/185552.html index 9dd26a5f..01ef7570 100644 --- a/groups.io/g/MTFHRT/wiki/29602/185552.html +++ b/groups.io/g/MTFHRT/wiki/29602/185552.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774522.1713918448130176431"); + console.log("client_id:", "web.web08.237609.1714523390862621082"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774522.1713918448130176431" + client_id: "web.web08.237609.1714523390862621082" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials made in USA <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/185742.html b/groups.io/g/MTFHRT/wiki/29602/185742.html index eddf1a12..cfb43953 100644 --- a/groups.io/g/MTFHRT/wiki/29602/185742.html +++ b/groups.io/g/MTFHRT/wiki/29602/185742.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775015.1713918448053441552"); + console.log("client_id:", "web.web08.237608.1714523390764598919"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775015.1713918448053441552" + client_id: "web.web08.237608.1714523390764598919" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=xp%2FSrRw2lxbcCgLkI8P8TiksdfY%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=j4x6h6ica3GcffulkYbo6snu%2B8k%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Ih1z%2FQ8xgypaysBrU1CtnLJPx7s%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919048&Signature=Z3jtxyGw6N2nqmUcUidAS%2BNOFCw%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/185743.html b/groups.io/g/MTFHRT/wiki/29602/185743.html index 5a28a10b..cb001122 100644 --- a/groups.io/g/MTFHRT/wiki/29602/185743.html +++ b/groups.io/g/MTFHRT/wiki/29602/185743.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775009.1713918447973773560"); + console.log("client_id:", "web.web09.237201.1714523390676978284"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775009.1713918447973773560" + client_id: "web.web09.237201.1714523390676978284" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/185980.html b/groups.io/g/MTFHRT/wiki/29602/185980.html index 5cfa4bfa..5cde9969 100644 --- a/groups.io/g/MTFHRT/wiki/29602/185980.html +++ b/groups.io/g/MTFHRT/wiki/29602/185980.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.775003.1713918447891239057"); + console.log("client_id:", "web.web08.237601.1714523390584297156"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.775003.1713918447891239057" + client_id: "web.web08.237601.1714523390584297156" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/186269.html b/groups.io/g/MTFHRT/wiki/29602/186269.html index b9ccb2e2..b5b0a0aa 100644 --- a/groups.io/g/MTFHRT/wiki/29602/186269.html +++ b/groups.io/g/MTFHRT/wiki/29602/186269.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774504.1713918447813670347"); + console.log("client_id:", "web.web08.237597.1714523390489800769"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774504.1713918447813670347" + client_id: "web.web08.237597.1714523390489800769" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/186348.html b/groups.io/g/MTFHRT/wiki/29602/186348.html index 0b74204b..742616b2 100644 --- a/groups.io/g/MTFHRT/wiki/29602/186348.html +++ b/groups.io/g/MTFHRT/wiki/29602/186348.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774993.1713918447737025378"); + console.log("client_id:", "web.web08.237595.1714523390390047684"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774993.1713918447737025378" + client_id: "web.web08.237595.1714523390390047684" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/186514.html b/groups.io/g/MTFHRT/wiki/29602/186514.html index 5f9d095e..ee0275a9 100644 --- a/groups.io/g/MTFHRT/wiki/29602/186514.html +++ b/groups.io/g/MTFHRT/wiki/29602/186514.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774991.1713918447656340918"); + console.log("client_id:", "web.web09.237188.1714523390299278481"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774991.1713918447656340918" + client_id: "web.web09.237188.1714523390299278481" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/186633.html b/groups.io/g/MTFHRT/wiki/29602/186633.html index e3506541..654a847b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/186633.html +++ b/groups.io/g/MTFHRT/wiki/29602/186633.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774494.1713918447581931726"); + console.log("client_id:", "web.web09.237185.1714523390209025514"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774494.1713918447581931726" + client_id: "web.web09.237185.1714523390209025514" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/186634.html b/groups.io/g/MTFHRT/wiki/29602/186634.html index d6b2ac4b..3f05eb0e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/186634.html +++ b/groups.io/g/MTFHRT/wiki/29602/186634.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774486.1713918447500526832"); + console.log("client_id:", "web.web08.237583.1714523390114438557"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774486.1713918447500526832" + client_id: "web.web08.237583.1714523390114438557" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/186944.html b/groups.io/g/MTFHRT/wiki/29602/186944.html index eee1d369..b52edcfe 100644 --- a/groups.io/g/MTFHRT/wiki/29602/186944.html +++ b/groups.io/g/MTFHRT/wiki/29602/186944.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774977.1713918447416143344"); + console.log("client_id:", "web.web08.237579.1714523390022501117"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774977.1713918447416143344" + client_id: "web.web08.237579.1714523390022501117" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=HcGIysMBvjJuc7c79YY31VKq%2F0c%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=SbDjJfLv0Zl3zpaCqqkfP44uW4I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=mzNJqTWKOvEdmoA2FcrLycCB2SA%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523990&Signature=W%2FbxxkzfhwAEuwGYYRi%2B7t29NZc%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/186993.html b/groups.io/g/MTFHRT/wiki/29602/186993.html index 230d2e67..362f861d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/186993.html +++ b/groups.io/g/MTFHRT/wiki/29602/186993.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774476.1713918447337235082"); + console.log("client_id:", "web.web09.237171.1714523389932866884"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774476.1713918447337235082" + client_id: "web.web09.237171.1714523389932866884" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187032.html b/groups.io/g/MTFHRT/wiki/29602/187032.html index dd5696d3..1dcc7ef6 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187032.html +++ b/groups.io/g/MTFHRT/wiki/29602/187032.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774967.1713918447244072961"); + console.log("client_id:", "web.web08.237569.1714523389831297406"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774967.1713918447244072961" + client_id: "web.web08.237569.1714523389831297406" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187071.html b/groups.io/g/MTFHRT/wiki/29602/187071.html index 733b193c..14a364e1 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187071.html +++ b/groups.io/g/MTFHRT/wiki/29602/187071.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774469.1713918447169955538"); + console.log("client_id:", "web.web09.237162.1714523389737796197"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774469.1713918447169955538" + client_id: "web.web09.237162.1714523389737796197" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187072.html b/groups.io/g/MTFHRT/wiki/29602/187072.html index 03a1a1f8..2d5ad7ff 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187072.html +++ b/groups.io/g/MTFHRT/wiki/29602/187072.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774463.1713918447098857832"); + console.log("client_id:", "web.web08.237558.1714523389641632346"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774463.1713918447098857832" + client_id: "web.web08.237558.1714523389641632346" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187073.html b/groups.io/g/MTFHRT/wiki/29602/187073.html index db5359d8..f67ce82a 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187073.html +++ b/groups.io/g/MTFHRT/wiki/29602/187073.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774455.1713918447024443907"); + console.log("client_id:", "web.web08.237548.1714523389546896757"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774455.1713918447024443907" + client_id: "web.web08.237548.1714523389546896757" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=gxST6XHfucoW%2BNp7N5oF5zW%2Btw8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=YixJ9OkTxutsAsRyik7StFyDk1c%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/223836409810" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/223836409810</a><br/><a href="https://www.aliexpress.com/item/33024594919.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/33024594919.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=H3kRdkkW8TC6tb1B9wwrQXDwkio%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919047&Signature=7p0EVUgXzwgbznt9VSlGzLwzdmo%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187215.html b/groups.io/g/MTFHRT/wiki/29602/187215.html index db447e59..40dbea96 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187215.html +++ b/groups.io/g/MTFHRT/wiki/29602/187215.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774935.1713918446943651909"); + console.log("client_id:", "web.web09.237141.1714523389451083355"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774935.1713918446943651909" + client_id: "web.web09.237141.1714523389451083355" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187225.html b/groups.io/g/MTFHRT/wiki/29602/187225.html index 5e3046c9..dd851e2e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187225.html +++ b/groups.io/g/MTFHRT/wiki/29602/187225.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774927.1713918446865215445"); + console.log("client_id:", "web.web08.237540.1714523389345652516"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774927.1713918446865215445" + client_id: "web.web08.237540.1714523389345652516" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187258.html b/groups.io/g/MTFHRT/wiki/29602/187258.html index eb568c8e..07dd3993 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187258.html +++ b/groups.io/g/MTFHRT/wiki/29602/187258.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774428.1713918446785271110"); + console.log("client_id:", "web.web09.237134.1714523389255609460"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774428.1713918446785271110" + client_id: "web.web09.237134.1714523389255609460" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187259.html b/groups.io/g/MTFHRT/wiki/29602/187259.html index c7aeca1c..bdfeb6cd 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187259.html +++ b/groups.io/g/MTFHRT/wiki/29602/187259.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774425.1713918446713704124"); + console.log("client_id:", "web.web08.237532.1714523389159951084"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774425.1713918446713704124" + client_id: "web.web08.237532.1714523389159951084" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187324.html b/groups.io/g/MTFHRT/wiki/29602/187324.html index 87ca0149..a6f7b7b7 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187324.html +++ b/groups.io/g/MTFHRT/wiki/29602/187324.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774919.1713918446636332478"); + console.log("client_id:", "web.web09.237124.1714523389070227407"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774919.1713918446636332478" + client_id: "web.web09.237124.1714523389070227407" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=KZH2qFBx4blQxpofSLTMw%2FyQlQM%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=pdUT0U7BUnstqKu3MIQjCpHrC6I%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=becQ%2B%2Bna0uLWzxnDWup3gEznmbg%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a>, and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523989&Signature=t%2F0F5Dxx3R1FTn0UKPDoo9DRK1o%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187370.html b/groups.io/g/MTFHRT/wiki/29602/187370.html index 16b13b3f..af6da2f8 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187370.html +++ b/groups.io/g/MTFHRT/wiki/29602/187370.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774420.1713918446558449285"); + console.log("client_id:", "web.web09.237120.1714523388980587673"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774420.1713918446558449285" + client_id: "web.web09.237120.1714523388980587673" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">on ebay</a> or Amazon and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187371.html b/groups.io/g/MTFHRT/wiki/29602/187371.html index a1d65317..c513137d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187371.html +++ b/groups.io/g/MTFHRT/wiki/29602/187371.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774914.1713918446478418813"); + console.log("client_id:", "web.web09.237113.1714523388887076390"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774914.1713918446478418813" + client_id: "web.web09.237113.1714523388887076390" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187424.html b/groups.io/g/MTFHRT/wiki/29602/187424.html index 9320382a..475b1aee 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187424.html +++ b/groups.io/g/MTFHRT/wiki/29602/187424.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774416.1713918446403767819"); + console.log("client_id:", "web.web08.237512.1714523388789254945"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774416.1713918446403767819" + client_id: "web.web08.237512.1714523388789254945" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187581.html b/groups.io/g/MTFHRT/wiki/29602/187581.html index 1363ae6c..a259e714 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187581.html +++ b/groups.io/g/MTFHRT/wiki/29602/187581.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774410.1713918446328747940"); + console.log("client_id:", "web.web08.237509.1714523388694445826"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774410.1713918446328747940" + client_id: "web.web08.237509.1714523388694445826" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187590.html b/groups.io/g/MTFHRT/wiki/29602/187590.html index b41f9ceb..b79b6088 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187590.html +++ b/groups.io/g/MTFHRT/wiki/29602/187590.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774900.1713918446248465260"); + console.log("client_id:", "web.web08.237507.1714523388603105001"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774900.1713918446248465260" + client_id: "web.web08.237507.1714523388603105001" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187593.html b/groups.io/g/MTFHRT/wiki/29602/187593.html index 7164ebb8..eb44828b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187593.html +++ b/groups.io/g/MTFHRT/wiki/29602/187593.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774892.1713918446141874440"); + console.log("client_id:", "web.web09.237100.1714523388511865670"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774892.1713918446141874440" + client_id: "web.web09.237100.1714523388511865670" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187707.html b/groups.io/g/MTFHRT/wiki/29602/187707.html index 2b877800..71df0dbe 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187707.html +++ b/groups.io/g/MTFHRT/wiki/29602/187707.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774394.1713918446062069568"); + console.log("client_id:", "web.web08.237502.1714523388412253722"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774394.1713918446062069568" + client_id: "web.web08.237502.1714523388412253722" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187775.html b/groups.io/g/MTFHRT/wiki/29602/187775.html index 58784bed..75b8657c 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187775.html +++ b/groups.io/g/MTFHRT/wiki/29602/187775.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774392.1713918445983911852"); + console.log("client_id:", "web.web09.237096.1714523388324692477"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774392.1713918445983911852" + client_id: "web.web09.237096.1714523388324692477" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=fHm74Zki9ytH9Sqdrc%2F1DBSneMs%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=w3s9FL9m6BfqXU80PJOGuSqcpTU%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=bOD0dnfvKDAI6EvXCy1EUG3ezkE%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919046&Signature=xQsGLCWS7QgEb8Yvylb2ujXAzVY%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187810.html b/groups.io/g/MTFHRT/wiki/29602/187810.html index f2707024..ef66e251 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187810.html +++ b/groups.io/g/MTFHRT/wiki/29602/187810.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774885.1713918445905449631"); + console.log("client_id:", "web.web08.237495.1714523388226786992"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774885.1713918445905449631" + client_id: "web.web08.237495.1714523388226786992" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187811.html b/groups.io/g/MTFHRT/wiki/29602/187811.html index 01728b77..e99ceafd 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187811.html +++ b/groups.io/g/MTFHRT/wiki/29602/187811.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774386.1713918445825121168"); + console.log("client_id:", "web.web09.237087.1714523388139476448"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774386.1713918445825121168" + client_id: "web.web09.237087.1714523388139476448" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187839.html b/groups.io/g/MTFHRT/wiki/29602/187839.html index f96c391c..3e365f6c 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187839.html +++ b/groups.io/g/MTFHRT/wiki/29602/187839.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774879.1713918445751488494"); + console.log("client_id:", "web.web09.237082.1714523388049128089"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774879.1713918445751488494" + client_id: "web.web09.237082.1714523388049128089" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=R6%2BUQu%2FwrOEE7Qi8N4YBUkVxSRk%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=G3vX1rcwXm1f%2B%2FmPY%2FekntkpcdQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=nqOyI4BjlNfMiucYZWlDgPwbULI%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523988&Signature=%2B5uOfd9zCMUnoUXMk%2BAh%2Fl1Bhow%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187840.html b/groups.io/g/MTFHRT/wiki/29602/187840.html index 7a512cbc..0e48dc7d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187840.html +++ b/groups.io/g/MTFHRT/wiki/29602/187840.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774382.1713918445659621710"); + console.log("client_id:", "web.web08.237481.1714523387952664036"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774382.1713918445659621710" + client_id: "web.web08.237481.1714523387952664036" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187847.html b/groups.io/g/MTFHRT/wiki/29602/187847.html index b3100986..c8db3d5a 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187847.html +++ b/groups.io/g/MTFHRT/wiki/29602/187847.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774874.1713918445584779418"); + console.log("client_id:", "web.web09.237075.1714523387862734374"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774874.1713918445584779418" + client_id: "web.web09.237075.1714523387862734374" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -685,10 +1056,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -701,7 +1072,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -806,66 +1177,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -875,9 +1210,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -906,48 +1239,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -962,13 +1290,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -990,7 +1322,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1011,138 +1343,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1164,6 +1502,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/187896.html b/groups.io/g/MTFHRT/wiki/29602/187896.html index a1d17860..dd5a9195 100644 --- a/groups.io/g/MTFHRT/wiki/29602/187896.html +++ b/groups.io/g/MTFHRT/wiki/29602/187896.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774374.1713918445509809788"); + console.log("client_id:", "web.web08.237475.1714523387768524465"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774374.1713918445509809788" + client_id: "web.web08.237475.1714523387768524465" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188033.html b/groups.io/g/MTFHRT/wiki/29602/188033.html index 63c434d6..472ef995 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188033.html +++ b/groups.io/g/MTFHRT/wiki/29602/188033.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774864.1713918445432805014"); + console.log("client_id:", "web.web09.237068.1714523387677746778"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774864.1713918445432805014" + client_id: "web.web09.237068.1714523387677746778" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188034.html b/groups.io/g/MTFHRT/wiki/29602/188034.html index 427dcaa4..788d8987 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188034.html +++ b/groups.io/g/MTFHRT/wiki/29602/188034.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774860.1713918445354357780"); + console.log("client_id:", "web.web08.237465.1714523387583156075"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774860.1713918445354357780" + client_id: "web.web08.237465.1714523387583156075" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188214.html b/groups.io/g/MTFHRT/wiki/29602/188214.html index f692a9e8..eda83aeb 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188214.html +++ b/groups.io/g/MTFHRT/wiki/29602/188214.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774358.1713918445278072489"); + console.log("client_id:", "web.web09.237059.1714523387491102279"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774358.1713918445278072489" + client_id: "web.web09.237059.1714523387491102279" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188232.html b/groups.io/g/MTFHRT/wiki/29602/188232.html index c7ed2cf4..87a759ec 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188232.html +++ b/groups.io/g/MTFHRT/wiki/29602/188232.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774845.1713918445200615334"); + console.log("client_id:", "web.web08.237459.1714523387392863431"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774845.1713918445200615334" + client_id: "web.web08.237459.1714523387392863431" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188240.html b/groups.io/g/MTFHRT/wiki/29602/188240.html index c0df0f15..4f8b2870 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188240.html +++ b/groups.io/g/MTFHRT/wiki/29602/188240.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774836.1713918445121680678"); + console.log("client_id:", "web.web08.237452.1714523387295030660"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774836.1713918445121680678" + client_id: "web.web08.237452.1714523387295030660" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In Europe you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188243.html b/groups.io/g/MTFHRT/wiki/29602/188243.html index ae8429fe..b92faa73 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188243.html +++ b/groups.io/g/MTFHRT/wiki/29602/188243.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774336.1713918445045865080"); + console.log("client_id:", "web.web09.237047.1714523387203955868"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774336.1713918445045865080" + client_id: "web.web09.237047.1714523387203955868" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=ahQhdECEo9hSTNwIwLqWR9SU5TU%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=5qK7Kfk2A6RhbGBm8ffMvg2YFQk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=2HqzTJdmgakdlYImeLrHabfFWbs%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In UK <a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety", just waste of money following prejudices.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919045&Signature=7KQWnJA%2B6jzWAuhVbE2nUmkYWH4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188266.html b/groups.io/g/MTFHRT/wiki/29602/188266.html index a2be9fc6..b609f8ef 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188266.html +++ b/groups.io/g/MTFHRT/wiki/29602/188266.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774332.1713918444971143908"); + console.log("client_id:", "web.web08.237449.1714523387109526108"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774332.1713918444971143908" + client_id: "web.web08.237449.1714523387109526108" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In UK <a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188385.html b/groups.io/g/MTFHRT/wiki/29602/188385.html index 2d5adfd2..7fba2157 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188385.html +++ b/groups.io/g/MTFHRT/wiki/29602/188385.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774329.1713918444895885944"); + console.log("client_id:", "web.web09.237042.1714523387015067131"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774329.1713918444895885944" + client_id: "web.web09.237042.1714523387015067131" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=IvTrGz5MOqNFUDbkmua7vNoNRVw%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=MVzUODlSHTr2JkBCFF%2BWOrTQA0s%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=QfYTh5BB703xUgXSOwWNqi6GZ4Q%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In UK <a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523987&Signature=w96vqEdri1jhk3AprAa4AygBjK0%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188427.html b/groups.io/g/MTFHRT/wiki/29602/188427.html index 6a9e473c..efff0863 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188427.html +++ b/groups.io/g/MTFHRT/wiki/29602/188427.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774818.1713918444817841362"); + console.log("client_id:", "web.web08.237440.1714523386911437609"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774818.1713918444817841362" + client_id: "web.web08.237440.1714523386911437609" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In UK <a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/188484.html b/groups.io/g/MTFHRT/wiki/29602/188484.html index fd43f885..b8f7d206 100644 --- a/groups.io/g/MTFHRT/wiki/29602/188484.html +++ b/groups.io/g/MTFHRT/wiki/29602/188484.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774306.1713918444742306032"); + console.log("client_id:", "web.web09.237034.1714523386817236585"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774306.1713918444742306032" + client_id: "web.web09.237034.1714523386817236585" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In UK <a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/189123.html b/groups.io/g/MTFHRT/wiki/29602/189123.html index 33f0f79f..76ae48bf 100644 --- a/groups.io/g/MTFHRT/wiki/29602/189123.html +++ b/groups.io/g/MTFHRT/wiki/29602/189123.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774299.1713918444668005098"); + console.log("client_id:", "web.web08.237434.1714523386708663077"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774299.1713918444668005098" + client_id: "web.web08.237434.1714523386708663077" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In UK <a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -807,66 +1178,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -876,9 +1211,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -907,48 +1240,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -963,13 +1291,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -991,7 +1323,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1012,138 +1344,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1165,6 +1503,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/189321.html b/groups.io/g/MTFHRT/wiki/29602/189321.html index 830272db..9f453090 100644 --- a/groups.io/g/MTFHRT/wiki/29602/189321.html +++ b/groups.io/g/MTFHRT/wiki/29602/189321.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774288.1713918444591951626"); + console.log("client_id:", "web.web09.237028.1714523386618143005"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774288.1713918444591951626" + client_id: "web.web09.237028.1714523386618143005" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener">эта инструкция по-русски</a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In UK <a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -808,66 +1179,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -877,9 +1212,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -908,48 +1241,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -964,13 +1292,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -992,7 +1324,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1013,138 +1345,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1166,6 +1504,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/189646.html b/groups.io/g/MTFHRT/wiki/29602/189646.html index 2db39a57..451303bb 100644 --- a/groups.io/g/MTFHRT/wiki/29602/189646.html +++ b/groups.io/g/MTFHRT/wiki/29602/189646.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774285.1713918444518577173"); + console.log("client_id:", "web.web08.237424.1714523386503563658"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774285.1713918444518577173" + client_id: "web.web08.237424.1714523386503563658" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/item/4000586480263.html</a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener">mites</a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/185908326110</a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener">https://www.aliexpress.us/item/2251832717628622.html</a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener">vials</a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener">1</a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener">2</a>,  <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener">caps</a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a> and <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a> in one shop, or <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a>. In UK <a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a>. In USA <a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener">BA</a>, <a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a> or <a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener">here</a> or (the cheapest) <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a>. In Canada <a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener">stoppers</a>+<a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener">BA</a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener">eBay</a> or <a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a> and buy <a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -808,66 +1179,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -877,9 +1212,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -908,48 +1241,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -964,13 +1292,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -992,7 +1324,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1013,138 +1345,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1166,6 +1504,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/189647.html b/groups.io/g/MTFHRT/wiki/29602/189647.html index 7554b7e8..661628af 100644 --- a/groups.io/g/MTFHRT/wiki/29602/189647.html +++ b/groups.io/g/MTFHRT/wiki/29602/189647.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774778.1713918444431817015"); + console.log("client_id:", "web.web09.237014.1714523386410892974"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774778.1713918444431817015" + client_id: "web.web09.237014.1714523386410892974" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -808,66 +1179,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -877,9 +1212,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -908,48 +1241,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -964,13 +1292,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -992,7 +1324,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1013,138 +1345,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1166,6 +1504,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/189700.html b/groups.io/g/MTFHRT/wiki/29602/189700.html index ee634f92..ae1ed80f 100644 --- a/groups.io/g/MTFHRT/wiki/29602/189700.html +++ b/groups.io/g/MTFHRT/wiki/29602/189700.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774279.1713918444355368485"); + console.log("client_id:", "web.web08.237415.1714523386308428309"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774279.1713918444355368485" + client_id: "web.web08.237415.1714523386308428309" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -808,66 +1179,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -877,9 +1212,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -908,48 +1241,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -964,13 +1292,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -992,7 +1324,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1013,138 +1345,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1166,6 +1504,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/189952.html b/groups.io/g/MTFHRT/wiki/29602/189952.html index 5f406b5a..00f0efc4 100644 --- a/groups.io/g/MTFHRT/wiki/29602/189952.html +++ b/groups.io/g/MTFHRT/wiki/29602/189952.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774769.1713918444274332994"); + console.log("client_id:", "web.web09.237010.1714523386214903318"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774769.1713918444274332994" + client_id: "web.web09.237010.1714523386214903318" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -670,7 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -686,10 +1057,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -702,7 +1073,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -808,66 +1179,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -877,9 +1212,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -908,48 +1241,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -964,13 +1292,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -992,7 +1324,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1013,138 +1345,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1166,6 +1504,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/190227.html b/groups.io/g/MTFHRT/wiki/29602/190227.html index f99fd67b..2bd5a802 100644 --- a/groups.io/g/MTFHRT/wiki/29602/190227.html +++ b/groups.io/g/MTFHRT/wiki/29602/190227.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774267.1713918444196971329"); + console.log("client_id:", "web.web08.237412.1714523386113249350"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774267.1713918444196971329" + client_id: "web.web08.237412.1714523386113249350" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -809,66 +1180,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -878,9 +1213,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -909,48 +1242,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -965,13 +1293,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -993,7 +1325,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1014,138 +1346,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1167,6 +1505,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/190628.html b/groups.io/g/MTFHRT/wiki/29602/190628.html index 6429bac5..51bcbdb4 100644 --- a/groups.io/g/MTFHRT/wiki/29602/190628.html +++ b/groups.io/g/MTFHRT/wiki/29602/190628.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774264.1713918444121202965"); + console.log("client_id:", "web.web09.237004.1714523386021797553"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774264.1713918444121202965" + client_id: "web.web09.237004.1714523386021797553" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=U2vCPVdHyRjUqandh%2FITM9tr6yo%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=6gOyfdkAbk0nasdvC%2FoC0S0K2bQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=KMuomK4Yyw8%2BxeNN%2FCU04TB6%2F4w%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523986&Signature=vlYT%2FykAYzm1Y9zLBU2iMCgpUXM%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -809,66 +1180,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -878,9 +1213,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -909,48 +1242,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -965,13 +1293,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -993,7 +1325,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1014,138 +1346,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1167,6 +1505,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/190629.html b/groups.io/g/MTFHRT/wiki/29602/190629.html index 79198b86..57e8a924 100644 --- a/groups.io/g/MTFHRT/wiki/29602/190629.html +++ b/groups.io/g/MTFHRT/wiki/29602/190629.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774758.1713918444040530332"); + console.log("client_id:", "web.web09.236998.1714523385928061403"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774758.1713918444040530332" + client_id: "web.web09.236998.1714523385928061403" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=qCM0eMXYCdtO4PCBoM9ZcSI84O8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=ujPNe98lBYjeqwIu98UC%2Fw5mGTQ%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=T%2BeOxLCwOL%2FGLvLrtKL7PUq%2Bpts%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919044&Signature=WuDdsEwG%2F1%2FgymYzI%2B2LCuMB77o%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -809,66 +1180,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -878,9 +1213,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -909,48 +1242,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -965,13 +1293,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -993,7 +1325,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1014,138 +1346,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1167,6 +1505,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/190846.html b/groups.io/g/MTFHRT/wiki/29602/190846.html index 75f6e7be..9cc874f2 100644 --- a/groups.io/g/MTFHRT/wiki/29602/190846.html +++ b/groups.io/g/MTFHRT/wiki/29602/190846.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774260.1713918443963783580"); + console.log("client_id:", "web.web09.236992.1714523385837446230"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774260.1713918443963783580" + client_id: "web.web09.236992.1714523385837446230" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -809,66 +1180,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -878,9 +1213,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -909,48 +1242,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -965,13 +1293,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -993,7 +1325,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1014,138 +1346,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1167,6 +1505,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/190847.html b/groups.io/g/MTFHRT/wiki/29602/190847.html index 76b4cd32..de4e8ae2 100644 --- a/groups.io/g/MTFHRT/wiki/29602/190847.html +++ b/groups.io/g/MTFHRT/wiki/29602/190847.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774750.1713918443884728713"); + console.log("client_id:", "web.web08.237386.1714523385740908070"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774750.1713918443884728713" + client_id: "web.web08.237386.1714523385740908070" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/190872.html b/groups.io/g/MTFHRT/wiki/29602/190872.html index 5e05513e..3bcc3d08 100644 --- a/groups.io/g/MTFHRT/wiki/29602/190872.html +++ b/groups.io/g/MTFHRT/wiki/29602/190872.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774250.1713918443806589690"); + console.log("client_id:", "web.web09.236974.1714523385649991163"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774250.1713918443806589690" + client_id: "web.web09.236974.1714523385649991163" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/190915.html b/groups.io/g/MTFHRT/wiki/29602/190915.html index fb790e93..f1b0435d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/190915.html +++ b/groups.io/g/MTFHRT/wiki/29602/190915.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774744.1713918443719813910"); + console.log("client_id:", "web.web08.237368.1714523385552282337"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774744.1713918443719813910" + client_id: "web.web08.237368.1714523385552282337" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/190942.html b/groups.io/g/MTFHRT/wiki/29602/190942.html index 3ac14449..c2e2afca 100644 --- a/groups.io/g/MTFHRT/wiki/29602/190942.html +++ b/groups.io/g/MTFHRT/wiki/29602/190942.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774244.1713918443640159234"); + console.log("client_id:", "web.web08.237359.1714523385452864755"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774244.1713918443640159234" + client_id: "web.web08.237359.1714523385452864755" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/191406.html b/groups.io/g/MTFHRT/wiki/29602/191406.html index 1a2cee69..82a6d026 100644 --- a/groups.io/g/MTFHRT/wiki/29602/191406.html +++ b/groups.io/g/MTFHRT/wiki/29602/191406.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774241.1713918443551776740"); + console.log("client_id:", "web.web08.237355.1714523385349696846"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774241.1713918443551776740" + client_id: "web.web08.237355.1714523385349696846" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/191417.html b/groups.io/g/MTFHRT/wiki/29602/191417.html index 66720b0e..6b6eee90 100644 --- a/groups.io/g/MTFHRT/wiki/29602/191417.html +++ b/groups.io/g/MTFHRT/wiki/29602/191417.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774737.1713918443471033565"); + console.log("client_id:", "web.web09.236945.1714523385257710275"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774737.1713918443471033565" + client_id: "web.web09.236945.1714523385257710275" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/191626.html b/groups.io/g/MTFHRT/wiki/29602/191626.html index edd2535d..fae97f0b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/191626.html +++ b/groups.io/g/MTFHRT/wiki/29602/191626.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774734.1713918443385879135"); + console.log("client_id:", "web.web08.237343.1714523385160598600"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774734.1713918443385879135" + client_id: "web.web08.237343.1714523385160598600" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/192624.html b/groups.io/g/MTFHRT/wiki/29602/192624.html index 14d2c747..0df2218f 100644 --- a/groups.io/g/MTFHRT/wiki/29602/192624.html +++ b/groups.io/g/MTFHRT/wiki/29602/192624.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774730.1713918443302447136"); + console.log("client_id:", "web.web08.237341.1714523385063480564"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774730.1713918443302447136" + client_id: "web.web08.237341.1714523385063480564" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=AKJ%2BFeYfFISBUYx0D4%2F8rPiXAL4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=MkwKWerE67P%2FaRqVK5za9cWm234%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=P89S%2FgJTtYCt%2BiOlHoKcprtcxlo%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523985&Signature=20PSobKVvlCTrO46j1X9unYOBYo%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/193627.html b/groups.io/g/MTFHRT/wiki/29602/193627.html index 5a14b393..a99ec17a 100644 --- a/groups.io/g/MTFHRT/wiki/29602/193627.html +++ b/groups.io/g/MTFHRT/wiki/29602/193627.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774726.1713918443218153132"); + console.log("client_id:", "web.web09.236934.1714523384968275668"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774726.1713918443218153132" + client_id: "web.web09.236934.1714523384968275668" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/194218.html b/groups.io/g/MTFHRT/wiki/29602/194218.html index b935139b..d59125fa 100644 --- a/groups.io/g/MTFHRT/wiki/29602/194218.html +++ b/groups.io/g/MTFHRT/wiki/29602/194218.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774723.1713918443139585127"); + console.log("client_id:", "web.web08.237335.1714523384861514417"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774723.1713918443139585127" + client_id: "web.web08.237335.1714523384861514417" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/194253.html b/groups.io/g/MTFHRT/wiki/29602/194253.html index 3088f9e7..50a955c4 100644 --- a/groups.io/g/MTFHRT/wiki/29602/194253.html +++ b/groups.io/g/MTFHRT/wiki/29602/194253.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774226.1713918443062608745"); + console.log("client_id:", "web.web09.236923.1714523384770257958"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774226.1713918443062608745" + client_id: "web.web09.236923.1714523384770257958" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/194629.html b/groups.io/g/MTFHRT/wiki/29602/194629.html index 12e68beb..bc0390e1 100644 --- a/groups.io/g/MTFHRT/wiki/29602/194629.html +++ b/groups.io/g/MTFHRT/wiki/29602/194629.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774224.1713918442986883832"); + console.log("client_id:", "web.web08.237318.1714523384667436976"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774224.1713918442986883832" + client_id: "web.web08.237318.1714523384667436976" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=1B%2Ff05j2BIBgqX3DVIGXcPdqLhg%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=Gs5jBs7AxzzRVtMEYdBiXyVvUlo%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=VbkNgC4C%2BF202mtT27CGNnvTu8A%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919043&Signature=8ONNF4xFWGqJZMynT1cBv45rUo0%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/194635.html b/groups.io/g/MTFHRT/wiki/29602/194635.html index 98b2e8d9..b6105c5c 100644 --- a/groups.io/g/MTFHRT/wiki/29602/194635.html +++ b/groups.io/g/MTFHRT/wiki/29602/194635.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774718.1713918442906818354"); + console.log("client_id:", "web.web09.236911.1714523384579859760"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774718.1713918442906818354" + client_id: "web.web09.236911.1714523384579859760" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/194867.html b/groups.io/g/MTFHRT/wiki/29602/194867.html index 79e91338..11f670e9 100644 --- a/groups.io/g/MTFHRT/wiki/29602/194867.html +++ b/groups.io/g/MTFHRT/wiki/29602/194867.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774716.1713918442830619635"); + console.log("client_id:", "web.web09.236905.1714523384491843190"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774716.1713918442830619635" + client_id: "web.web09.236905.1714523384491843190" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/194939.html b/groups.io/g/MTFHRT/wiki/29602/194939.html index e9e92e47..f9e69f4f 100644 --- a/groups.io/g/MTFHRT/wiki/29602/194939.html +++ b/groups.io/g/MTFHRT/wiki/29602/194939.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774215.1713918442754815136"); + console.log("client_id:", "web.web09.236899.1714523384399617103"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774215.1713918442754815136" + client_id: "web.web09.236899.1714523384399617103" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>).</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/195405.html b/groups.io/g/MTFHRT/wiki/29602/195405.html index 7c85ea23..4ba7ad62 100644 --- a/groups.io/g/MTFHRT/wiki/29602/195405.html +++ b/groups.io/g/MTFHRT/wiki/29602/195405.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774210.1713918442679716716"); + console.log("client_id:", "web.web08.237299.1714523384300610375"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774210.1713918442679716716" + client_id: "web.web08.237299.1714523384300610375" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vials+10ml+stoppers+caps</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/195973.html b/groups.io/g/MTFHRT/wiki/29602/195973.html index 4fc7a44b..09bb5d68 100644 --- a/groups.io/g/MTFHRT/wiki/29602/195973.html +++ b/groups.io/g/MTFHRT/wiki/29602/195973.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774703.1713918442597048526"); + console.log("client_id:", "web.web08.237294.1714523384204172433"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774703.1713918442597048526" + client_id: "web.web08.237294.1714523384204172433" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/195986.html b/groups.io/g/MTFHRT/wiki/29602/195986.html index c6a29fec..44fc4b49 100644 --- a/groups.io/g/MTFHRT/wiki/29602/195986.html +++ b/groups.io/g/MTFHRT/wiki/29602/195986.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774202.1713918442519209515"); + console.log("client_id:", "web.web09.236890.1714523384114391652"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774202.1713918442519209515" + client_id: "web.web09.236890.1714523384114391652" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/196048.html b/groups.io/g/MTFHRT/wiki/29602/196048.html index 605cd5fa..306cf2ea 100644 --- a/groups.io/g/MTFHRT/wiki/29602/196048.html +++ b/groups.io/g/MTFHRT/wiki/29602/196048.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774695.1713918442436296701"); + console.log("client_id:", "web.web08.237290.1714523384019792621"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774695.1713918442436296701" + client_id: "web.web08.237290.1714523384019792621" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PdETn4HB%2Bz1pPhenr6ZBIays6%2B4%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=PwQvAduZx9U6wQK8027ZtV1kHRk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=uA%2FtZ1vQ67YQ8cjkWEzvT8BEp50%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523984&Signature=sTC7Wz2z4nmS1vtE8ULFmngt%2FeI%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/196085.html b/groups.io/g/MTFHRT/wiki/29602/196085.html index 35e60567..6d3ed333 100644 --- a/groups.io/g/MTFHRT/wiki/29602/196085.html +++ b/groups.io/g/MTFHRT/wiki/29602/196085.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774198.1713918442358211234"); + console.log("client_id:", "web.web09.236880.1714523383927786682"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774198.1713918442358211234" + client_id: "web.web09.236880.1714523383927786682" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/196597.html b/groups.io/g/MTFHRT/wiki/29602/196597.html index c3c7a14e..3b94936c 100644 --- a/groups.io/g/MTFHRT/wiki/29602/196597.html +++ b/groups.io/g/MTFHRT/wiki/29602/196597.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774691.1713918442274853582"); + console.log("client_id:", "web.web09.236875.1714523383835733768"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774691.1713918442274853582" + client_id: "web.web09.236875.1714523383835733768" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/197239.html b/groups.io/g/MTFHRT/wiki/29602/197239.html index e1815cd9..f131aa9d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/197239.html +++ b/groups.io/g/MTFHRT/wiki/29602/197239.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774191.1713918442194199178"); + console.log("client_id:", "web.web09.236870.1714523383744930602"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774191.1713918442194199178" + client_id: "web.web09.236870.1714523383744930602" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/197796.html b/groups.io/g/MTFHRT/wiki/29602/197796.html index a2e0c4e7..3e0e2ca8 100644 --- a/groups.io/g/MTFHRT/wiki/29602/197796.html +++ b/groups.io/g/MTFHRT/wiki/29602/197796.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774187.1713918442118795892"); + console.log("client_id:", "web.web08.237269.1714523383632871158"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774187.1713918442118795892" + client_id: "web.web08.237269.1714523383632871158" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or (the cheapest) <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials on <a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+sterile&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=240" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">eBay</span></a> or <span style="text-decoration: underline;"><a href="https://www.amazon.com/Depyrogenated-Sterile-Clear-Borosillicate-Glass/dp/B077KFKKJM/" target="_blank" rel="nofollow noopener">Amazon</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/197814.html b/groups.io/g/MTFHRT/wiki/29602/197814.html index b8f5ba8b..5b3cd2ed 100644 --- a/groups.io/g/MTFHRT/wiki/29602/197814.html +++ b/groups.io/g/MTFHRT/wiki/29602/197814.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774680.1713918442040840260"); + console.log("client_id:", "web.web09.236858.1714523383542696956"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774680.1713918442040840260" + client_id: "web.web09.236858.1714523383542696956" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=ZkrYjTFLVRFBsPk2T%2Beh6Dtdme8%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=pxwqs%2FxvOaVAAgEqdlqcphAKk3g%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=B3pmrFm3nXbY1M1CpA%2FKuYv1%2BVk%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">sealed vials</a></span>+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919042&Signature=hII4IgS9ywj1erMW%2BVpSLNq8Xl4%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/197818.html b/groups.io/g/MTFHRT/wiki/29602/197818.html index 3edb92d6..3549b074 100644 --- a/groups.io/g/MTFHRT/wiki/29602/197818.html +++ b/groups.io/g/MTFHRT/wiki/29602/197818.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774181.1713918441964035054"); + console.log("client_id:", "web.web08.237257.1714523383438586475"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774181.1713918441964035054" + client_id: "web.web08.237257.1714523383438586475" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/197828.html b/groups.io/g/MTFHRT/wiki/29602/197828.html index dbfee0d5..78e10741 100644 --- a/groups.io/g/MTFHRT/wiki/29602/197828.html +++ b/groups.io/g/MTFHRT/wiki/29602/197828.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774675.1713918441886588240"); + console.log("client_id:", "web.web09.236845.1714523383348964577"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774675.1713918441886588240" + client_id: "web.web09.236845.1714523383348964577" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/197829.html b/groups.io/g/MTFHRT/wiki/29602/197829.html index 160c025c..3db922ee 100644 --- a/groups.io/g/MTFHRT/wiki/29602/197829.html +++ b/groups.io/g/MTFHRT/wiki/29602/197829.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774671.1713918441805510709"); + console.log("client_id:", "web.web08.237244.1714523383249544019"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774671.1713918441805510709" + client_id: "web.web08.237244.1714523383249544019" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/197830.html b/groups.io/g/MTFHRT/wiki/29602/197830.html index fc356bb0..1acc5c9d 100644 --- a/groups.io/g/MTFHRT/wiki/29602/197830.html +++ b/groups.io/g/MTFHRT/wiki/29602/197830.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774175.1713918441729987735"); + console.log("client_id:", "web.web09.236838.1714523383158398164"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774175.1713918441729987735" + client_id: "web.web09.236838.1714523383158398164" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/197997.html b/groups.io/g/MTFHRT/wiki/29602/197997.html index 2adf0226..283148d4 100644 --- a/groups.io/g/MTFHRT/wiki/29602/197997.html +++ b/groups.io/g/MTFHRT/wiki/29602/197997.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774667.1713918441651766213"); + console.log("client_id:", "web.web09.236835.1714523383068772022"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774667.1713918441651766213" + client_id: "web.web09.236835.1714523383068772022" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=4ABK5CBHitZkYbnFjaxdRCbXlF0%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=dLmwZ1iT8vpeDD8pb5hp79Eerjc%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=0mzQBn70yaN%2BGMvBZqliEalvxZM%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523983&Signature=MBVC8fMgHuPu8XOWLLG6MEC3Y1U%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/198070.html b/groups.io/g/MTFHRT/wiki/29602/198070.html index 8aed654c..5b61e6d3 100644 --- a/groups.io/g/MTFHRT/wiki/29602/198070.html +++ b/groups.io/g/MTFHRT/wiki/29602/198070.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774662.1713918441570873922"); + console.log("client_id:", "web.web09.236831.1714523382971234373"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774662.1713918441570873922" + client_id: "web.web09.236831.1714523382971234373" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/198075.html b/groups.io/g/MTFHRT/wiki/29602/198075.html index d8a79f8b..009e202a 100644 --- a/groups.io/g/MTFHRT/wiki/29602/198075.html +++ b/groups.io/g/MTFHRT/wiki/29602/198075.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774659.1713918441488904114"); + console.log("client_id:", "web.web08.237229.1714523382873201190"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774659.1713918441488904114" + client_id: "web.web08.237229.1714523382873201190" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/198774.html b/groups.io/g/MTFHRT/wiki/29602/198774.html index 90870cd8..d13d10e3 100644 --- a/groups.io/g/MTFHRT/wiki/29602/198774.html +++ b/groups.io/g/MTFHRT/wiki/29602/198774.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774160.1713918441410265211"); + console.log("client_id:", "web.web08.237224.1714523382775643471"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774160.1713918441410265211" + client_id: "web.web08.237224.1714523382775643471" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/199148.html b/groups.io/g/MTFHRT/wiki/29602/199148.html index 69bc32fd..9344b30b 100644 --- a/groups.io/g/MTFHRT/wiki/29602/199148.html +++ b/groups.io/g/MTFHRT/wiki/29602/199148.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774652.1713918441330386366"); + console.log("client_id:", "web.web09.236819.1714523382684572223"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774652.1713918441330386366" + client_id: "web.web09.236819.1714523382684572223" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -810,66 +1181,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -879,9 +1214,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -910,48 +1243,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -966,13 +1294,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -994,7 +1326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1015,138 +1347,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1168,6 +1506,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/199960.html b/groups.io/g/MTFHRT/wiki/29602/199960.html index 1cefacc9..07c70f27 100644 --- a/groups.io/g/MTFHRT/wiki/29602/199960.html +++ b/groups.io/g/MTFHRT/wiki/29602/199960.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774156.1713918441248614026"); + console.log("client_id:", "web.web08.237218.1714523382578411888"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774156.1713918441248614026" + client_id: "web.web08.237218.1714523382578411888" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -811,66 +1182,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -880,9 +1215,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -911,48 +1244,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -967,13 +1295,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -995,7 +1327,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1016,138 +1348,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1169,6 +1507,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/201192.html b/groups.io/g/MTFHRT/wiki/29602/201192.html index 7663f84e..0a595423 100644 --- a/groups.io/g/MTFHRT/wiki/29602/201192.html +++ b/groups.io/g/MTFHRT/wiki/29602/201192.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774154.1713918441174371915"); + console.log("client_id:", "web.web09.236809.1714523382477996667"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774154.1713918441174371915" + client_id: "web.web09.236809.1714523382477996667" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -811,66 +1182,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -880,9 +1215,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -911,48 +1244,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -967,13 +1295,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -995,7 +1327,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1016,138 +1348,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1169,6 +1507,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/201237.html b/groups.io/g/MTFHRT/wiki/29602/201237.html index 38c55405..172487e1 100644 --- a/groups.io/g/MTFHRT/wiki/29602/201237.html +++ b/groups.io/g/MTFHRT/wiki/29602/201237.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774643.1713918441093333522"); + console.log("client_id:", "web.web08.237208.1714523382379302732"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774643.1713918441093333522" + client_id: "web.web08.237208.1714523382379302732" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -811,66 +1182,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -880,9 +1215,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -911,48 +1244,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -967,13 +1295,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -995,7 +1327,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1016,138 +1348,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1169,6 +1507,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/202979.html b/groups.io/g/MTFHRT/wiki/29602/202979.html index 60ecee9d..85fe147e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/202979.html +++ b/groups.io/g/MTFHRT/wiki/29602/202979.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774145.1713918441015755354"); + console.log("client_id:", "web.web08.237203.1714523382279618208"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774145.1713918441015755354" + client_id: "web.web08.237203.1714523382279618208" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -671,7 +1042,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=aVDKX9J7Z18iH2WG8z8zhTb1VjA%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -687,10 +1058,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=DWJZJgJ78NT4LeYVycW0z3jYAfk%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=XPDuNsnICCDYkM7whJb5KYsj3Tc%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -703,7 +1074,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919041&Signature=2Y7uT4JZgzZe704AGUR5fbHYPZ8%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -811,66 +1182,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -880,9 +1215,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -911,48 +1244,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -967,13 +1295,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -995,7 +1327,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1016,138 +1348,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1169,6 +1507,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/203230.html b/groups.io/g/MTFHRT/wiki/29602/203230.html index 36ae2e09..68ff342e 100644 --- a/groups.io/g/MTFHRT/wiki/29602/203230.html +++ b/groups.io/g/MTFHRT/wiki/29602/203230.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774635.1713918440933482173"); + console.log("client_id:", "web.web09.236797.1714523382189829445"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774635.1713918440933482173" + client_id: "web.web09.236797.1714523382189829445" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Ultimate DIY</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,32 +927,75 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="../30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="../30846.html"> + Home + </a> + </li> + + <li> + <a href="../32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="../34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="../29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> Last edited <script id="timedispupdated29602"> - $('#timedispupdated29602').replaceWith(DisplayShortTime(1713169488373935500, false + $('#timedispupdated29602').replaceWith(DisplayShortTime(1714463966229202489, false )); </script> · <a href="history.html"> - 265 revisions + 266 revisions </a>    <a href="../29602.html"> <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <p style="text-align: center;"><span style="font-size: 24pt;">MtF HRT: Ultimate DIY</span></p> <p>Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.</p> <p style="text-align: right;"><a href="https://groups.io/g/TGrus/wiki/Ultimate-DIY" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">эта инструкция по-русски</span></a></p> @@ -672,7 +1043,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Equipment"></a>Equipment</h2> <h3><a name="Necessary"></a>Necessary</h3> <p>The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).</p> -<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919040&Signature=0F5fTNI6532cH8a3K8az%2FbqWjsI%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> +<p>If you buy ready-to-use scales then they must look exactly like this:<br/><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13908/354x254.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=BCAKtE9hKKMentySoHE8YMuZsjU%3D" align="right" class="myimg-responsive"/><span style="text-decoration: underline;"><a href="https://www.ebay.com/itm/363747240371" target="_blank" rel="nofollow noopener">https://www.ebay.com/itm/363747240371</a></span><br/><a href="https://www.aliexpress.com/item/4000586480263.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/item/4000586480263.html</span></a></p> <p>Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.</p> <p>Search for other sellers:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1</span></a></p> <p><a href="https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1</span></a></p> @@ -688,10 +1059,10 @@ function createAlert(msg, isError, autoClose, noClose) { <p>Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and <a href="https://en.wikipedia.org/wiki/House_dust_mite" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">mites</span></a>) if never washed. Water - bacteria - pyrogens. Hormone powders are sold not sterile, so any cleaning / sterilization efforts before terminal heat sterilization are futile. Don't try to improve this technology: it protects you from mistakes and unexpected problems.</p> <h2><a name="Other-raw-materials-and-expendables"></a>Other raw materials and expendables</h2> <h3><a name="Vials2C-stoppers2C-caps"></a>Vials, stoppers, caps</h3> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919040&Signature=vDO5I2hCyG1DldEGAoVtQzrP%2Fmw%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13965/s-l300.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=7sFQVWYKEnVu3hUOZOx6eMaJlo4%3D" align="right" class="myimg-responsive"/>Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:<br/><a href="https://www.ebay.com/itm/185908326110" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/itm/185908326110</span></a><br/><a href="https://www.aliexpress.us/item/2251832717628622.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.us/item/2251832717628622.html</span></a><br/>Flat septa are not suitable instead of stoppers. Search:<br/><a href="https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1</span></a></p> <p><a href="https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap</span></a></p> <p>After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must <strong>not</strong> have tear-off weak place on one side like this:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919040&Signature=HC%2BR%2Bzb4uwhYCttQTXkbsOAoOYg%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13909/cap-tear-off.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=CQ6LPeW%2Btez3MxBrNukXwj8OA5E%3D" class="myimg-responsive"/></p> <p>In EU you can buy <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/VIC010-001NS" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>, stoppers <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22STG20-%200001%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">1</span></a> or <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/STR20-0001" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a>, <a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BKMA%2020-GO%22" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a>, <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22BA%200020%22" target="_blank" rel="nofollow noopener">benzyl alcohol</a></span> and <span style="text-decoration: underline;"><a href="https://lab-supply-shop.com/epages/171448.sf/en_GB/?ObjectPath=/Shops/171448/Products/%22MCT%201L%22" target="_blank" rel="nofollow noopener">MCT oil</a></span> in one shop, or (cheaper) <a href="https://www.glas-shop.com/glasprodukte/injektionsflascheninfusionsflaschen/injektionsflaschenklarglas5100ml/injektionsflasche-klarglas-10ml.php" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/injektionsstopfeneinzeln20mmrotausbrombutyl.php" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.glas-shop.com/verschluesse2/verschluesse-fuer-injektionsflaschen/boerdelkappe-2025-x-74-mm-mittel-abriss-gruen.php" target="_blank" rel="nofollow noopener">caps</a></span>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/Mikikit-Clear-Glass-Bottle-Transparent/dp/B09TPLQQRB/" target="_blank" rel="nofollow noopener">here</a></span>, or <a href="https://www.amazon.es/gp/product/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>, or <span style="text-decoration: underline;"><a href="https://www.amazon.de/-/en/H566EJW15X19NTIP4/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener">here</a></span>. In UK <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">here</a></span> or <a href="https://www.amazon.co.uk/Mikikit-10ml-Clear-Glass-Bottle/dp/B09TFPB6SR/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>. In USA <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/vials/open/rls-10ml-tubular-clear-glass-serum-vials-qty-1.html" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/butyl-rubber-stoppers-for-vials-20mm-gray.html" target="_blank" rel="nofollow noopener">stoppers</a></span>+<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/lab-supplies/20mm-standard-aluminum-seal-please-click-to-view-all-colors.html" target="_blank" rel="nofollow noopener">caps</a></span> (<span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/usp-oils/mct-60-40-caprylic-c8-capric-c10-oil.html" target="_blank" rel="nofollow noopener">oil</a></span>, <a href="https://www.medical-and-lab-supplies.com/chemicals-solvents/benzyl-alcohol-usp.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>, <span style="text-decoration: underline;"><a href="https://www.medical-and-lab-supplies.com/medical-supplies/syringes-and-needles/diabetic-syringes/aimsco-maxicomfort-diabetic-insulin-syringes.html" target="_blank" rel="nofollow noopener">syringes</a></span>) or <span style="text-decoration: underline;"><a href="https://lemelange.com/unsterilevialwide10ml20mm.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://lemelange.com/20-mm-vial-stoppers-grey.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://lemelange.com/20mmaluminumringwithcentertearout.aspx" target="_blank" rel="nofollow noopener">caps</a></span> or <a href="https://qcvialz.com/vial-samples/316-10ml-clear-shorty-serum-vials-iso-10r-24x45mm-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">vials</span></a>+<a href="https://qcvialz.com/vial-stopper-samples/319-20mm-round-bottom-vial-stopper-sample-pack-of-10.html" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://qcvialz.com/superior-flip-cap-vial-seals/482-light-blue-20mm-superior-flip-cap-vial-seals-pack-of-10pc.html" target="_blank" rel="nofollow noopener">caps</a></span> or <span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/110-10-ML-Unsealed-Clear-Vial.aspx" target="_blank" rel="nofollow noopener">vials</a></span>+<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/store/p/38-Grey-Butyl-Stopper.aspx" target="_blank" rel="nofollow noopener">stoppers</a></span>+<a href="https://www.gpzmedlab.com/store/p/102-Aluminum-Seal-Center-Tear-Out.aspx" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">caps</span></a> (<span style="text-decoration: underline;"><a href="https://www.gpzmedlab.com/easy-touch-1-cc-insulin-syringe-with-28-g-x-1-2-needle-100-count.aspx" target="_blank" rel="nofollow noopener">syringes</a></span>) or <a href="https://www.premiumvials.com/10ml-glass-bottle-with-lid-transparent-vial-b-10pcs/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a> or sealed vials(<span style="text-decoration: underline;"><a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener">1</a></span> <a href="https://www.amazon.com/10ml-Sterile-Vial-Blue-Flip/dp/B07JD49TK2/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">2</span></a> <a href="https://www.amazon.com/Biocomma-Aluminum-Caps%EF%BC%8CPenicillin-Transparent-Borosilicate/dp/B09W5HM7R6/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">3</span></a> <a href="https://www.amazon.com/Empty-Borosillicate-Sealed-Sterile-Serum/dp/B005DIPY32/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">4</span></a> <a href="https://www.amazon.com/5-10ml-Empty-Sealed-Sterile-Vials/dp/B009CC0KMA/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">5</span></a> <a href="https://www.amazon.com/Molded-Sterile-Clear-Vials-Black/dp/B07KVCL4YF/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">6</span></a>)+<a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">new caps</span></a>. In Canada <span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/10ml-vials-clear/products/10ml-vial-22mm-x-50mm-clear?variant=8081524817966" target="_blank" rel="nofollow noopener">vials</a></span>+<a href="https://canadianmedhealthsupplies.ca/collections/all-rubber-stoppers/products/20mm-rubber-stopper-grey?variant=8081553915950" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">stoppers</span></a>+<span style="text-decoration: underline;"><a href="https://canadianmedhealthsupplies.ca/collections/20mm-flip-off-cap-flip-off/products/20mm-white-flip-off-cap-flip-off" target="_blank" rel="nofollow noopener">caps</a></span> (<a href="https://canadianmedhealthsupplies.ca/collections/solvents/products/benzyl-alcohol" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">BA</span></a>). In Mexico <a href="https://varienvases.mx/products/antibiotico-10ml-con-tapon-y-casquillo?variant=42526677467355" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">here</span></a>.</p> <p>If you are paranoid and believe incompetent <a href="https://issuepedia.org/Sufficiently_advanced_incompetence_is_indistinguishable_from_malice" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">or</span></a> deceitful slander about this guide then you can buy washed sealed sterile empty vials from <a href="https://www.ebay.com/sch/257835/i.html?_dkr=1&iconV2Request=true&_blrs=recall_filtering&_ssn=texlabsupplyinternational&_oac=1&_ipg=240&_fcid=1&LH_BIN=1&_sop=15" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">USA</span></a> or <span style="text-decoration: underline;"><a href="https://www.ebay.co.uk/itm/333152620103" target="_blank" rel="nofollow noopener">UK</a></span> and buy <span style="text-decoration: underline;"><a href="https://www.amazon.com/20MM-13MM-Single-Seals-Eco-Green/dp/B094Q5VVTH/" target="_blank" rel="nofollow noopener">new caps</a></span> or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.</p> <h3><a name="Oil"></a>Oil</h3> @@ -704,7 +1075,7 @@ function createAlert(msg, isError, autoClose, noClose) { <h2><a name="Mix"></a>Mix</h2> <p>(See below for an alternate way without a funnel).</p> <p>Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:</p> -<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1713919040&Signature=oXY4lCz60DYyLp%2BweupwUGRWcys%3D" class="myimg-responsive"/></p> +<p><img src="https://s3-us-west-1.amazonaws.com/groupsiowikiimages/4415/13910/cone.jpg?AWSAccessKeyId=AKIAJECNKOVMCCU3ATNQ&Expires=1714523982&Signature=qBifQG%2FclMqnNomYXbQXTO3r5qY%3D" class="myimg-responsive"/></p> <p>Two recipes I can recommend:</p> <p>1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm<sup><small>3</small></sup>),<br/>benzyl alcohol (preservative - antibacterial) 0.2 ml,<br/>MCT oil 10-0.2-0.5/1.1= 9.35 ml.</p> <p>2) 0.5 g of estradiol enanthate,<br/>MCT oil 10-0.5/1.1= 9.55 ml.</p> @@ -812,66 +1183,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="../30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="../30846.html"> - Home - </a> - </li> - - <li> - <a href="../32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="../34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="../29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -881,9 +1216,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -912,48 +1245,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -968,13 +1296,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -996,7 +1328,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -1017,138 +1349,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1170,6 +1508,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/29602/204015.html b/groups.io/g/MTFHRT/wiki/29602/204015.html new file mode 100644 index 00000000..7a6c729c --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/29602/204015.html @@ -0,0 +1,1533 @@ + + + <!DOCTYPE html> + <html lang="en-US"> + <head> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <meta name="pinterest" content="nopin" /> + <meta name="pinterest" content="nohover" /> + + <meta name="3778517eb4810dfb5d143ed8f1b359b3b5a82923" content="0f56257c3db4a222e91b11bc6871c4df2e263b28" /> + <link rel="apple-touch-icon" sizes="57x57" href="https://groups.io/img/org.1/favicons/apple-icon-57x57.png"> + <link rel="apple-touch-icon" sizes="60x60" href="https://groups.io/img/org.1/favicons/apple-icon-60x60.png"> + <link rel="apple-touch-icon" sizes="72x72" href="https://groups.io/img/org.1/favicons/apple-icon-72x72.png"> + <link rel="apple-touch-icon" sizes="76x76" href="https://groups.io/img/org.1/favicons/apple-icon-76x76.png"> + <link rel="apple-touch-icon" sizes="114x114" href="https://groups.io/img/org.1/favicons/apple-icon-114x114.png"> + <link rel="apple-touch-icon" sizes="120x120" href="https://groups.io/img/org.1/favicons/apple-icon-120x120.png"> + <link rel="apple-touch-icon" sizes="144x144" href="https://groups.io/img/org.1/favicons/apple-icon-144x144.png"> + <link rel="apple-touch-icon" sizes="152x152" href="https://groups.io/img/org.1/favicons/apple-icon-152x152.png"> + <link rel="apple-touch-icon" sizes="180x180" href="https://groups.io/img/org.1/favicons/apple-icon-180x180.png"> + <link rel="icon" type="image/png" sizes="192x192" href="../../../../img/org.1/favicons/android-icon-192x192.png"> + <link rel="icon" type="image/png" sizes="32x32" href="../../../../img/org.1/favicons/favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="96x96" href="../../../../img/org.1/favicons/favicon-96x96.png"> + <link rel="icon" type="image/png" sizes="16x16" href="../../../../img/org.1/favicons/favicon-16x16.png"> + <link rel="manifest" href="../../../../img/org.1/favicons/manifest.json"> + <meta name="msapplication-TileColor" content="#ffffff"> + <meta name="msapplication-TileImage" content="/ms-icon-144x144.png"> + + + + +<script> +/* stubs */ +const hapticsImpactHeavy = async () => { +}; +const hapticsImpactMedium = async () => { +}; +const hapticsImpactLight = async () => { +}; +const hapticsVibrate = async () => { +}; +const hapticsSelectionStart = async () => { +}; +const hapticsSelectionChanged = async () => { +}; +const hapticsSelectionEnd = async () => { +}; +</script> + + +<script> + + function setPullToRefresh() {} + + function gotoURL(inurl) { + window.location.href = inurl; + return; + } + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); + if (isHTMX == true) { + document.body.addEventListener('htmx:afterSettle', f, {once: true}); + } else { + if (document.readyState !== 'loading') { + console.log('document is already ready, just execute code here'); + f(); + } else { + console.log('document was not ready, place code here'); + document.addEventListener('DOMContentLoaded', f, {once: true}); + } + } + } + + // stub + function logError(data, url, linenumber) { + console.log(data) + return; + } + var pushSubToken; + var ignoreErrors = false; + var lastError = ""; + + window.onerror = function(errorMessage, errorUrl, errorLine, errorColumn, errorObj) { + let column; + let stack; + if (console && console.log) { + console.log("msg:", errorMessage); + console.log("url:", errorUrl); + console.log("line:", errorLine); + if (errorColumn !== undefined && errorObj != null) { + console.log("column:", errorColumn); + column = errorColumn; + } + if (errorObj !== undefined && errorObj != null) { + console.log("stack:", errorObj.stack); + stack = errorObj.stack; + } + console.log("client_id:", "web.web08.237199.1714523382093620013"); + console.log("last_error:", lastError); + console.log("stack:", stack); + } + if (errorUrl == "" || errorUrl === null) { + errorUrl = window.location.href; + } + if (errorMessage.includes("SecurityError:") == true) { + ignoreErrors = true; + } + if (ignoreErrors == true) { + console.log("cookies, disabled, ignoring"); + lastError = errorMessage; + return; + } + jQuery.ajax({ + type: 'POST', + url: '/jsclienterror', + data: { + msg: errorMessage, + url: errorUrl, + line: errorLine, + column: column, + stack: stack, + last_error: lastError, + client_id: "web.web08.237199.1714523382093620013" + }, + success: function() { + if (console && console.log) { + console.log('JS error report successful.'); + } + lastError = errorMessage; + }, + error: function() { + if (console && console.error) { + console.error('JS error report submission failed!'); + } + lastError = errorMessage; + } + }); + return true; + } + +</script> + + + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> + <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> + <script src="../../../../js/run_prettify.js"></script> + <title> + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 266 revisions + +    + + + +
+ +
+
+ +
+
+ + +

MtF HRT: Ultimate DIY

+

Here I describe Do-It-Yourself hormonal treatment for male-to-female transsexuals/transgender: be your own gatekeeper, endocrinologist, pharmacist and nurse. Cook injectable estradiol by yourself. Safer, more effective and unbelievably cheaper than relying on medical professionals.

+

эта инструкция по-русски

+

+

Without gatekeepers

+

Endocrinologists usually require a letter/referral from gatekeepers: psychotherapists, psychologists, sexologists or psychiatrists. Not because endocrinologists care for you, but because they care for themselves: they fear that you regret and sue them for causing you bodily harm. There isn't a medical examination, blood or psychological test able to prove or disprove presence or absence of transsexualism in each separate person. Statistics is meaningless when the question is whether you'll regret social transition or not. So, gatekeepers make appearances of "examination" and stall you for long time while milking you (or insurance/taxpayers) for money.

+

Medical professionals routinely make mistakes in both directions: approve crazy people and unnecessarily delay transsexuals who'll not regret.

+

If you obtain or make hormones without prescription, you'll have nobody but yourself to blame if you regret social consequences of your decision to take hormones.

+

Be your own endocrinologist

+

Endocrinologists treat mostly diabetes and problems with thyroid. For that endos prescribe multiple blood tests and adjust meds dosages to drive blood glucose or T4 level into "normal range". Endos are used to such approach, it keeps them busy and paid. With the only goal to maximize quantity of doctor visits paid by patients or insurance, gangs of American endos write guidelines how to treat transsexuals: with same approach. All the numbers in such guidelines and all the bogeyman stories about side effects of estradiol are bullshit.

+

"Normal range" is from measurements of 90% of healthy people: 5% of lowest and 5% of highest results are discounted. Normal range of estradiol for pregnancy is up to 40000 pg/ml = 147000 pmol/l. In a group of 86 pregnant women estradiol level was up to 75137 pg/ml = 275753 pmol/l: http://cebp.aacrjournals.org/content/12/5/452.figures-only . Pregnant women don't drop dead from such estradiol level, so you wouldn't even if your peak reaches 5000 pg/ml.

+

It's even darker than that: the numbers in guidelines are chosen deliberately low to force transsexuals to pay for more doctor visits to beg for more estradiol.

+

Doctors also recall the mantra in their gospels (textbooks) about estrogens: dosage the less the better, stop as soon as possible. They never realize that this mantra was written in the fear of uterine cancer. And that you haven't an uterus.

+

Currently lifetime breast cancer risk for cis-women in North America is 13% because of hundreds of monthly hormonal cycles. Doctors believe "the more estrogen, the more breast cancer risk". But statistically, every pregnancy decreases the woman's breast cancer risk though during pregnancy blood estradiol level increases in hundred times. Explanation of this seeming contradiction: because every pregnancy decreases cumulative number of menstrual cycles. In more detail: At one phase of hormonal cycle ductal epithelium in milk glands proliferates (proliferation is tissue growth by cell division), at another phase apoptosis comes (tissue shrinking by cell suicide). Each cell division (mitosis) carries risk of mutation. Mutations cause cancer. Before advent of contraceptives, breast cancer was a disease of celibate nuns. A woman was pregnant, then breastfeeding for few years (that also usually suppresses menstruations), then quickly :) impregnated again and so on until death or menopause. Then a woman had few menstruations during her whole life. If you don't make monthly cycles then your breast cancer risk is as low as men's, no matter how high estradiol level.

+

Giving MtF low estrogen dosage alone doesn't work. So, doctors prescribe antiandrogens: spironolactone (dangerous and mostly ineffective) or cyproterone acetate (harmful, dangerous, counterproductive) or GnRH superagonists such as Lupron or Zoladex (insanely expensive) or bicalutamide (expensive, and very few endos heard of it, side effects listed in package insert seem dangerous though really they aren't). Doctors love to prescribe expensive meds because doctors' fee seems less significant in comparison. Most likely you'd be prescribed spironolactone or cyproterone acetate, so your doctor is hazardous for your health.

+

Why not to give more estradiol? Because largest estradiol pills nowadays are 2 mg. One pill a day according to the gospel (package insert) does nothing for MtF. No doctor would prescribe more than 4 pills a day. Medical school is cramming huge amount of info. Doctors aren't used to dig for numbers and to think by themselves. They blindly believe other doctors' opinions. No doctor managed to dig for numbers and calculate: birth control pills prescribed to over hundred million women contain ethinylestradiol 0.03 mg/day which affects liver and blood clotting 500 times stronger than oral estradiol, so risk from oral estradiol 0.03*500= 15 mg/day is considered acceptable. But estradiol 15 mg/day is 8 pills per day - seems too much for doctors. Simple arithmetic is alien science for them.
I'm an engineer, I'm not afraid of arithmetic. :) And I study MtF HRT in depth since 1989. In Italy ethinylestradiol 1000 mcg = 1 mg pills are available, so doctors there prescribe 2 such pills per day to MtF. That's as dangerous as oral estradiol 2*500= 1000 mg/day. And? Nobody notices. I conclude that oral estradiol 20 mg/day is okay.

+

MtF HRT with an estrogen without antiandrogens is called "monotherapy". Oral estradiol 20 mg/day (10 mg twice a day) suppresses testosterone production by testicles completely, so antiandrogens are unnecessary. You can mail-order estradiol pills from abroad, though expensive:
https://www.inhousepharmacy.vu/p-166-estrofem-2mg.aspx
https://www.inhousepharmacy.vu/p-2073-estradiol-2mg.aspx
https://www.inhousepharmacy.vu/p-1866-estrofem-tablets-2mg.asp
https://www.inhousepharmacy.vu/p-112680811-estradiol-tablets-2mg-epic-pharma-usa.aspx

+

Only 5% of swallowed estradiol reaches blood. Sublingually (under the tongue) or subbuccally (between a lip and a gum) gives better absorption, but I don't believe that more than in 1.5 times, can cause mood swings and soon becomes too inconvenient. Transdermal patches and gels with estradiol are even more expensive than pills. One more way to deliver estradiol is injections, 100% absorption. If the solution is concentrated then you can use insulin syringes. Estradiol valerate (EV) 40 mg/ml 0.18 ml every 5 days or estradiol enanthate (EEn) 50 mg/ml 0.22 ml weekly is as effective as oral estradiol 20 mg/day, but is cheaper. Factory-made injectable EV is available without prescription https://www.inhousepharmacy.vu/p-99900888-ar-estradiol-valerate-40mgml.aspx (though often out of stock, "expected" date is a lie: they just increase it). I make a copy 15 times cheaper than that, and I make EEn suitable for injections every 7 or 10 days: http://lena.kiev.ua/EV/ . Below I explain how you can cook injectable estradiol by yourself.

+

If you had male pattern baldness then add finasteride 0.05 - 0.1 mg (1/100 - 1/50 of a 5 mg pill) once a day, available in InHousePharmacy or AllDayChemist or DragonOrdnance or from me as an addition to ready-to-use injectable EV or EEn. Don't take dutasteride because of possible mental side effects (also, dutasteride accumulates in blood and continues to give side effects for months after stopping it). Finasteride is necessary despite complete suppression of testosterone production by testicles by injectable estradiol or/and surgical removal of testicles because of DHEA production by adrenals. Finasteride blocks DHEA->T->DHT conversion inside hair follicle cells which is unnoticed by blood tests.

+

I advise everybody (not only MtF) to take a vitamins+minerals supplement like this non-stop, all year round.

+

It really is that simple after you throw out all the bullshit about "physiological" or "target" levels and learn all the details which side effects are real and which aren't.

+

Why I chose this dosage to advise for monotherapy: with it I can be sure that it's enough for any MtF without blood tests. Different people on the same dosage get blood estradiol level differing in up to 10 times. Sensitivity of different people for the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. In USA a blood test without prescription costs $79 (1 2a+2b 3 4) and is available not everywhere. In UK £39 or £89. In Australia $69. In Canada $200 (1+2). In Netherlands €55. In Sweden $90 (1+2). In many countries only with prescription, and doctors refuse to prescribe tests for meds they didn't prescribe. My or DIY injectables without blood tests are cheaper than lower dosage with several blood tests. And no time wasted on determining barely enough dosage.

+

I don't believe that beginning from lower estradiol dosage (possible safely only with addition of bicalutamide) gives better results. Doctors love to begin from low estrogen dosage with lots of blood tests because this keeps them busy and paid. So they claim that it's allegedly better. Doctors in other countries parrot that. There isn't any evidence. People repeat doctors' claims.

+

In short: when it's about MtF HRT, doctors do not know better.

+

Cook your injectable estradiol by yourself

+

If you are attentive and diligent then you can make injectable estradiol by yourself (for yourself only) as I described below. If you are afraid or unsure then you can buy ready-to-use vials from me. I have over 3500 satisfied customers. I lost count how many times I was called lifesaver, fairy godmother, angel, godsend, saint.

+

May be you heard claims that I advocate unsafe, insufficient stirilization. Those scientifically-appearing (at first glance) claims (mentioning standards and quoting articles) were published as a marketing tool, to denigrate a competitor (me). Noone of my 3500 customers complained of infection. Why? Because actually it's the opposite: terminal heat sterilization is more reliable than filtering + aseptic procedures. I explained details to the disparager, she ignored explanations, never replied and didn't take down the belittling. I explained details below in the Equipment, Sterilize sections of this guide and separate explanation linked from Myths, but people who believe the marketing slander never read.

+

Buy estradiol enanthate powder

+

Don't buy estradiol valerate because it's inferior: requires injections every 5 days and either lower concentration (more oil to inject) or addition of a solvent (benzyl benzoate) which costs money and sometimes causes allergy. Both estradiol valerate and estradiol enanthate are converted to the same estradiol in blood, spleen and lymph nodes (in leukocytes: by carboxylesterase 1 in monocytes and macrophages and carboxylesterase 2 in plasma cells). Estradiol enanthate is absorbed into blood slower, that gives more stable blood estradiol level and allows longer time between injections.

+

Most of substances used by Western pharmaceutical manufacturers comes from chemical factories in China. There are vendors in China selling the same substances to anybody (private persons too), no questions asked. Testosterone is a controlled substance, estradiol isn't. Such vendors are not manufacturers of estradiol powder, just resellers/traders/retail. You'll never know who was the manufacturer (perhaps 1 2 3 4 5).

+

If in USA then you can buy EEn powder here (shipping $15).

+

In other countries currently I advise cheaper (for EEn powder quantities 20 g or less) vendor DragonOrdnance shipping from China. EEn powder from him was tested, it's the real thing. Also, he has multiple testimonials for anabolics and testosterone on bodybuilder forums. Shipping $50. "Stealth shipping" means that there may be (or not) also something else in the parcel besides the hidden bag with EEn powder, don't throw out anything. Descriptions on the parcel and on the bag inside are lies to fool Customs. Order 5, 10 or 20 g, and also 100 ml (minimal order) of MCT oil and 100 ml of benzyl alcohol. How to distinguish: the alcohol has an odor. Try coupon code: TransDIY
If you haven't crypto then you can buy LTC (Litecoin) or BTC (Bitcoin) directly to the vendor's wallet address using for example Paybis (or if in USA then you can use CashApp, perhaps not Paypal). Or you can pay with a card or local bank transfer via TransferWise (more fees).

+

A similar vendor PurplePanda has higher prices for MCT oil and benzyl alcohol.

+

If you have mild needle phobia and more money then you can buy 10 or 20 g of longer-acting (3-4 weeks) estradiol undecylate CAS 3571-53-7 from PurplePanda or hbldbiotech or hhd-pharm. I bought 1 kg EV from Hbldbiotech and 1 kg EEn from Aoksbio, got the real thing. But few of those many who bought 10-20 g EEn from them are dissatisfied: lost parcels, refused by Customs, not EEn at all (dissolves in water or doesn't dissolve in MCT oil). If the website redirects to the vendor's home page then use a VPN or proxy, for example a free browser extension browsec, country in the free list for example Netherlands. There are other vendors there, but it's a gamble: some sellers send unrelated white powder (not a hormone at all). Don't use a dishonest vendor "Vanz" (their another company name is "Wuhan Yiruo") and spammers "Faithful", "Luoxing", "Jiangsu Aimi", "Jiangsu Kaihuida", "Hebei Mingyi", "Xian Shunyi", "Shanxi Lianxu", "Shandong Xishun", "Jinan Future Chemical", "Guangzhou LingYue", "Zhejiang Aiyi", "Jinlan pharm"/royalpharms. Elsewhere I saw negative reviews about: "Wison". Don't use sellers touting anabolics etc. for bodybuilders on their main page: you don't want to get testosterone instead of estradiol. "Gzbiocar" seems suspicious for me. Salespeople on made-in-china use nicknames or European-sounding aliases, same was on Alibaba. You'll see a real Chinese name only if you pay via Western Union. Vendors' pages are full of mistakes and lies, including photos of manufacturing plants (they manufacture few substances if any but sell hundreds), numbers, prices and minimal order (MOQ). Register (type zeros instead of phone number and "private person" instead of company name) and after that use the "Get Latest Price" link (if you want EEn), tell them your requirement "Estradiol Enanthate (Estradiol Heptanoate) CAS 4956-37-0, I prefer powder with large particle size (not micronized)" and ask for price for quantity 20 g with the cheapest shipping. If the vendor answers with "FOB" price then that means not including shipping, ask again for cheapest shipping fee. Don't ask for CoA (certificate of analysis), it'd be fake. Really you'll get slightly better than 98% purity according to USP and similar standards for pharmaceuticals for humans, there isn't estradiol powder with any worse purity (manufacturers of veterinarian pharmaceuticals get the same purity); better purity ("reference standard") is used only for calibration of measuring equipment and costs for example €353 for 100 mg. Cheapest shipping gives also least chances of problems with Customs. The (separate) "forwarding" company they use knows what to lie on the Customs declaration; you may find also papers about an unrelated benign substance like vitamin C - also to fool Customs. Ignore offers/requests to communicate via Whatsapp or other messengers (never give them your number/nickname), don't reply to emails, reply to the vendor only via https://membercenter.made-in-china.com/message/index.html . Vendors offer several payment options, some vendors take payment via Alibaba (allows to pay with card and takes 3% fee). "Aoksbio" accepts Western Union, Bitcoin and SWIFT (wire/bank transfer), same total price for 10 and 20 g, so order 20 g. If you pay with bank transfer then "Aoksbio" may ask for your ID with the same name as in your bank account (if other payment options then ID is not required). If Western Union (WU) then you tell "Aoksbio" the 10-digit number WU gives you and sender name you gave to WU. If the vendor ignores your requirement and sends you micronized powder then it's suitable but more difficult to work with because clings to everything.

+

Please join this [MTFHRT] group (you must both "confirm" your email address with the link you'll be emailed and email an intro about yourself to moderators) and post prices and your experiences in detail, ask questions.

+

Equipment

+

Necessary

+

The only necessary equipment is cheap ($7 - $15) pocket 0.001 g (1 mg) scales (or DIY balance scales you can make from a long narrow wooden plank, 2 small nails and 2 syringes, one of them with 0.5 ml water as a precise weight).

+

If you buy ready-to-use scales then they must look exactly like this:
https://www.ebay.com/itm/363747240371
https://www.aliexpress.com/item/4000586480263.html

+

Newer models are not suitable because they attempt to appear more precise and stable by ignoring small weight changes.

+

Search for other sellers:
https://www.ebay.com/sch/i.html?_nkw=scale+0.001&_sacat=0&_blrs=recall_filtering&LH_BIN=1&_sop=15&_ipg=120&_oac=1

+

https://www.ebay.com/sch/i.html?_nkw=scale+digital+diamond&_sacat=0&LH_BIN=1&_sop=15&_blrs=recall_filtering&_ipg=120&_oac=1

+

https://www.aliexpress.com/wholesale?SearchText=scale+0.001+diamond
(check all pages).

+

If the scales have slots for 4 batteries then insert only 2 at any one side.

+

If you want fast shipping of 0.001 g scales within USA, these model and seller ($50) are okay. Can be bought cheaper on Amazon, model name may be different, but must look exactly same (only color may differ). In UK here. In Mexico here.

+

If you already have 0.01 g (not 0.1 g) scales then you may use them: precision 2% is enough as you make injectable for yourself only. In USA these model and seller ($7) are okay, fast shipping. In UK these or similar. In EU these.

+

Optional

+

The vials are designed to be sealed with rubber stoppers and aluminium caps using a tool (crimper, $36). But you can crimp a cap without a crimper: by hand using a piece of metal like a spoon handle.

+

You can buy a 129°C autoclave for $170 (1 2 3), but it's not really necessary as you make vials for yourself only. 121°C was necessary for obsolete reusable syringes with fresh blood of another patient because hepatitis B virus can survive 100°C for short time if in blood. You are not dealing with fresh blood, so 100°C (water boiling in a pot) is enough. I use an autoclave just for customers' peace of mind. At first I sold kits with EV powder, solvent, preservative and instructions how to mix and sterilize in a pot, multiple people including myself sterilized at 100°C, never a problem. If you live at significant altitude (like in Denver "mile high city") then likely you already have a pressure cooker. I advise against dry heat sterilizers and ovens because of too uneven temperature: too much can burst a vial, more than 135°C damages estradiol. Bead sterilizers not suitable. In USA you can buy a 15 PSI pressure cooker for $76, in UK £40, in EU €50, in other countries a pressure cooker with pressure 15 PSI = 100 kPa is more difficult to find: most sellers don't advertise pressure because it's less, so temperature is less than 121°C.

+

Years ago American "homebrewing" bodybuilders extracted trenbolone (an anabolic) from subcutaneous pellets for cattle. Trenbolone changes color and perhaps partially decomposes if heated. So, for sterilization they used filtering instead of heat. When Chinese companies began to sell anabolics and testosterone powders to anybody, bodybuilders continued to use only filtering for sterilization though testosterone (as well as estradiol) endures heating up to 275°F=135°C (but not more) without "deactivation" bodybuilders still fear. Terminal heat sterilization (of already mixed solution in sealed vials) became taboo for them though filtering is not a reliable sterilization: small bacteria, fungal spores, viruses can penetrate 0.2 μm filters. Thankfully, solutions of steroid esters in oils with BA, BB are not nutritious for bacteria: no water; three chemical elements C, H, O are not enough for bacterial growth. I can understand filtering for intravenous infusions liters per day (in ICU), but for our subcutaneous injections 1 ml/month filtering doesn't make sense, terminal heat sterilization is more reliable and easier than aseptic procedures. There were multiple complaints that some EV ampules made by pharmaceutical factories in India are fake. I think not deliberately fake but just incompetent technologists and managers: they mixed in a tank in an air-conditioned cold (to limit bacteria) room without solvent for not enough time, then undissolved powder got stuck in a filter. If you are paranoid and insist on following the filtering fad then wait several days until every last clump of powder finishes dissolving in a vial, then use a PTFE or PVDF 0.22 μm syringe filter (not hydrophilic, better 25 or 33 mm), a 10 ml Luer Lock syringe and optionally a homemade filtering rig, I made mine (for paranoid customers, I don't filter what I inject into myself) from 4 stacks of books, a piece of plywood/MDF with a hole for the syringe, a wide wooden plank/board, a 6 L (1.5 gallon) plastic bottle with water as a weight, the plank slightly tilted and leaning on a wall for stability. And anyway sterilize the sealed vial you filtered into at 100-130°C after filtering!

+

Unnecessary

+

Unnecessary: beaker, mixer/stirrer, room with controlled airflow, depyrogenation. My technology: terminal heat sterilization (after the vials are sealed); measure and mix in each vial separately, so no glassware to wash with water  or collecting dust (skin flakes and mites) if never washed. Water - bacteria - pyrogens. Hormone powders are sold not sterile, so any cleaning / sterilization efforts before terminal heat sterilization are futile. Don't try to improve this technology: it protects you from mistakes and unexpected problems.

+

Other raw materials and expendables

+

Vials, stoppers, caps

+

Buy 10 clear glass vials 10 ml each with 20 mm grey (butyl rubber) stoppers and aluminium caps. Caps may be bare aluminium or painted, with plastic tops or all-metal. Screw-on and all-plastic caps are not suitable. Stoppers must have this shape:
https://www.ebay.com/itm/185908326110
https://www.aliexpress.us/item/2251832717628622.html
Flat septa are not suitable instead of stoppers. Search:
https://www.ebay.com/sch/i.html?_nkw=vial+10ml+stopper+cap&_sacat=0&LH_TitleDesc=0&LH_BIN=1&_sop=15&_oac=1

+

https://www.aliexpress.com/wholesale?SearchText=vial+10ml+stopper+cap

+

After you remove central part of the cap, most of the cap must remain and hold the rubber stopper at place. Caps must not have tear-off weak place on one side like this:

+

+

In EU you can buy vials, stoppers 1 or 2, caps, benzyl alcohol and MCT oil in one shop, or (cheaper) vials+stoppers+caps, or here, or here, or here. In UK here or here. In USA vials+stoppers+caps (oil, BA, syringes) or vials+stoppers+caps or vials+stoppers+caps or vials+stoppers+caps (syringes) or here or sealed vials(1 2 3 4 5 6)+new caps. In Canada vials+stoppers+caps (BA). In Mexico here.

+

If you are paranoid and believe incompetent or deceitful slander about this guide then you can buy washed sealed sterile empty vials from USA or UK and buy new caps or carefully unbend crimped caps with a small flat screwdriver. Really it'd not improve "safety". But in USA and UK these vials are cheaper if you want fast shipping.

+

Oil

+

MCT oil (liquid, not powder, not in capsules, without flavor added) made from a mix of C8 (caprylic) and C10 (capric) fatty acids (not C8 only) - cheapest bottle you can find, in a local sports nutrition store or mail-order, but not the "Dr.Adorable" brand and must not contain the word "fractionated" in description. MCT oil made from coconut oil unlikely to cause allergy, but made from palm kernel oil or "palm derived" even less likely. It's the only ingredient with somewhat limited shelf life: roughly 5 years as rumored though bottles are usually marked with arbitrary shelf life 2 years. You'll use up 10 ml per year. In USA you can mail-order a 2 oz (60 ml) sample bottle on eBay for $6 including shipping. Check prices also on Amazon. In EU here. In local stores smallest bottle can be 400 ml, roughly $13. MCT oil is marketed as a food supplement to be taken 15 ml/day, taken orally is rapidly absorbed. You'll inject 500 times less, so any purity is okay (it's really all the same purity despite some dishonest sellers' claims).

+

Preservative

+

If you can, add a preservative (antibacterial): benzyl alcohol. You'll use up 8 ml for 30 years. If you buy EEn powder from DragonOrdnance then buy also benzyl alcohol and MCT oil there in the same order, likely that'd be cheaper. Else usually cheaper on eBay. Look also for companies selling ingredients for perfumes, cosmetics, soap crafting, for example in Europe here (they also sell MCT oil under another name), or here (and oil), or here, or here, or here. In Australia here. In Canada here. In USA here. If you don't add the preservative then make sure that each time you draw from a sterilized vial, you take a new syringe. I inject myself with estradiol enanthate in MCT oil without preservative because of my allergy.

+

Syringes for mixing

+

Measure MCT oil with a 10 ml (or 5 ml) syringe. If you can find an all-plastic syringe without (usually black) rubber at the inner end of the plunger then one syringe will last you forever. Else likely you'll have to take a new disposable syringe every time you cook a few vials (up to 5 years apart) because the oil very slowly spoils that rubber. Vial stoppers are made from resistant rubber.

+

If you add a preservative then use one of syringes you bought for injections (see below) to measure 0.2 ml.

+

Mix

+

(See below for an alternate way without a funnel).

+

Make a small funnel from a piece of foil (the thicker foil the better; shinier side inside), hold it folded with a small piece of sticky tape. If you have only thin foil then perhaps strengthen it by wide sticky tape on another side (or try to strip the outer paint from a few different beer or soft drink aluminium cans with nail polish remover, then cut a clean can with scissors). May be use something conical to wrap the foil around before cutting off unneeded parts. The hole at the pointy end of the funnel must be slightly (not much) smaller than the opening in the vial. Use this funnel to weigh up estradiol enanthate powder and to pour the powder into a vial. The funnel I'm using at the center, unfolded piece of foil from my previous funnel at the left, a funnel in a vial at the right:

+

+

Two recipes I can recommend:

+

1) 500 mg = 0.5 g of estradiol enanthate (density 1.1 g/cm3),
benzyl alcohol (preservative - antibacterial) 0.2 ml,
MCT oil 10-0.2-0.5/1.1= 9.35 ml.

+

2) 0.5 g of estradiol enanthate,
MCT oil 10-0.5/1.1= 9.55 ml.

+

If you see that this amount of the mix doesn't fit entirely in the wide part of the vial and goes into narrower vial neck then these Chinese vials are too small, then after complete dissolution use an insulin syringe to throw out 1 ml of the solution, and make next vials with 8 ml, recipes:
1) 0.4 g of estradiol enanthate,
benzyl alcohol 0.16 ml,
MCT oil 8-0.16-0.4/1.1= 7.5 ml;
2) 0.4 g of estradiol enanthate,
MCT oil 8-0.4/1.1= 7.65 ml.

+

Sit comfortably at a table, put the scales onto the center of a sheet of blank paper ("landscape" orientation: width more than height). Put the funnel onto the circle on the scales, pointy side to the left (as at the center of the photo above). Turn the scales on, wait for 0.000
Take estradiol enanthate powder from the bag on the tip of a small knife, pour onto the funnel over the center of the circle on the scales until the scales show any number between 0.501 and 0.503
If you poured too much, take excess powder off with the knife tip. Don't fuss over part of powder which may fall off through the pointy end of the funnel or elsewhere, it's what the paper sheet is for.

+

Take an empty vial with fingers of left hand, put the vial hole to the pointy end of the funnel. Lightly press the funnel into the vial with left index finger (it's the most tricky part: you must prevent the funnel from falling off the vial and spilling the powder, but you must press lightly to not crumple the foil). Carefully rotate the vial upright together with the funnel over the paper sheet while continuing holding the funnel in the vial with the left index finger. Take a plastic pen or wooden pencil with right hand, tap lightly multiple times on the glass vial you hold in left hand fingers to shake the funnel until all the powder pours from the funnel into the vial.

+

If some powder fell off, use knife tip to put most of it back into the bag.

+

An alternate way without a funnel: take a roll of usual kitchen foil (any thickness), with scissors cut a square about 5 cm (2") on a side. Touch only corners of the square (because powder can stick to fingerprints). The square should be pristine, without creases. Put the square on the scales, turn the scales on. Take some estradiol enanthate powder from the bag with knife tip, pour onto the square. Then more, until the scales show any number between 0.501 and 0.503 . If you poured too much, take the excess back with knife tip. Put an empty vial onto the paper sheet near the scales. Put two fingers under centers of two opposite sides of the square, bend the square until those two sides come together. Then clench these two sides together with fingers of another hand, take the square with powder off the scales. Pour the powder from the square into a vial. When you mix next vial, perhaps cut a new pristine square.

+

Now you may optionally draw 0.2 ml of benzyl alcohol into a syringe, pour it into the vial over the powder and watch as the powder sags a little and partially dissolves.

+

Measure the MCT oil with a syringe and pour into the vial.

+

Close the vial with the rubber stopper, put the cap onto the stopper. While pressing the cap onto the vial, put the vial upside down (cap down) onto a book. While pressing the vial down, bend the rim of the cap in several (8-10) places with a spoon handle so that the cap holds the stopper at place. Don't press too strongly to not shatter the glass.

+

While clenching the vial with two fingers at bottom and cap, shake up the vial thoroughly during a full minute (it's a long time).

+

Wait several days, shake up the first vial few times each day. The warmer in the room, the faster dissolving. If the powder dissolved completely to clear solution then you were sold the real thing and enough pure. For next vials don't wait.

+

Another way to make sure that you got really estradiol enanthate is checking melting point of the powder: it may be 94-114°C. A simpler way to check melting point: measure/pour 500 mg more powder into another vial, don't pour liquids yet, close the vial, but bend the cap rim in only 3 places. Put the vial into a pot with tap water, boil the water (while watching the powder in it), turn the heat off, wait for the water to cool off, take the vial out of the water. If the powder partly solidified and doesn't all move completely freely in the vial then it's the real thing. Few oil-soluble substances have such relatively low melting point. But if melting point of the powder you got happens to be slightly more than 100°C then this test is inconclusive: you'd need a pressure cooker or an autoclave to heat the vial to slightly more than 100°C, or this way. After the test unbend the cap, open the vial, pour liquid[s], seal, and now you'll have to wait for much longer time (up to a month) until the solidified part of the powder dissolves.

+

For estradiol undecylate (EU, melting point 105-110°C): recipes (60 mg/ml):
1. EU 0.6 g, benzyl alcohol 0.2 ml, MCT oil 10-0.2-0.6/1.07= 9.25 ml or
2. (for allergics) EU 0.6 g, MCT oil 10-0.6/1.07= 9.45 ml.
Inject 0.83 ml monthly or 0.62 ml every 3 weeks.

+

Sterilize

+

For sterilization put the sealed vial into a pot with tap water, after that boil the water, keep the water boiling for 30 min, turn off the heat, wait until the water cools off. The cap darkens - that doesn't matter. If you already have any pressure cooker (or a multi-cooker with pressure cooker function) then use it instead of a pot (vial submerged in water), else a pot is enough!

+

If you sterilize more than one vial at a time then tie them together with cotton thread, put them into the pot upright and pour tap water up to about 1/3 of vial height. If you sterilize one vial then bubbling boiling water shakes the vial, it makes unusual clattering sound.

+

Instead of water you can use any oil in a small pot (also vials upright, the oil up to 1/3 of vial height), but then you need a thermometer: manually continuously adjust heat from the stove to maintain 130°C (266°F) for 30 min. Or you can use oil in a multi-cooker if it hasn't pressure cooker function but can maintain 130°C. Before sterilization in such oil bath, wait for complete dissolution of the powder.

+

During sterilization the powder finishes dissolving. Shake up the vial (ignore tiny bubbles).

+

Wash off limescale (calcium carbonate from heated tap water) from the vial with cloth wet with vinegar.

+

Let the vial to dry, handwrite "estradiol enanthate 50 mg/ml" in small letters on paper in 3 lines, cut that out (the smaller label the better) and glue it onto the vial with a piece of transparent sticky tape just slightly larger than the label.

+

Possibly you heard advices to use a flow hood, gloves, mask, to disinfect or sterilize empty vials, stoppers, hands, the table or whole room and so on. All these efforts are completely futile if you use the most reliable method of sterilization I advise (called "terminal heat sterilization"): heating already mixed and sealed vials by submersion in boiling water, or oil heated to 130°C.

+

Begin a new vial

+

If the aluminium cap is all-metal without plastic top then the cap has 2 or 3 incisions in a circle at the center of the top of the cap. Either tear off the center of a cap (hold to not pull entire cap off) or cut it out using small scissors with sharp tips to expose central part of the rubber stopper underneath. Don't pierce the rubber stopper.

+

If your caps are with plastic tops then stick a flat screwdriver or a knife under the top, the top should detach with the central part of the cap. If you accidentally pulled entire cap off and the rubber stopper came out of the vial then fix the cap back and repeat sterilization.

+

The very center of the rubber stopper is marked with smaller circle - it's where needles should be inserted.

+

Keep

+

Keep the powder sealed airtight in a vial or in bags with as little air as possible. Keep the powder, mixed but yet unused vials, benzyl alcohol and oil wrapped in foil to protect from light. Keep the vial you are using in a box, drawer or cupboard. Not in a fridge. Keep at room temperature (whatever it is), upright. Before use, look at the bottom of a vial: if it became white instead of transparent then put the vial at a warm place, and EEn will dissolve back, the warmer the faster. Then shake up the vial (ignore tiny bubbles).

+

Total price

+

Here I use prices (including shipping) I saw at the time of this writing for people living in USA:

+

quantity 1 (10 g) of estradiol enanthate powder + $15 shipping = $65
benzyl alcohol $7.99
250 ml MCT oil 1 or 2 $9.99
Scales $7.06
syringes 5-10 ml (for measuring MCT oil) $4.23
10 vials with stoppers and caps $12.99
100 syringes for injections $15.39

+

10 g of estradiol enanthate powder will be enough to cook 20 vials which will last you 20*10/0.223*7/365= 17 years.

+

Initial expenses 65+7.99+9.99+7.06+4.23+12.99+15.39 = $123

+

Total expenses during 17 years (123+2*9.99+12.99+8*15.39)/(17.2*12)= $1.37 per month. A hundred times cheaper for safer and much more effective HRT than doctor-prescribed. And you don't depend on doctors' whims and meds shortages.

+

Another example for UK:
5 g EEn powder + 100 ml benzyl alcohol + 100 ml MCT oil + payment fee = £83.43
scales £4.99
vials+stoppers+caps £14.99
syringe 5ml £1.63
100 syringes 1ml £19.13
Total £124 for 9 vials - for 7.7 years, £2 per month (including 4 packs of syringes 1ml).

+

Legal

+

If you make injectable estradiol for yourself only, no problem. But if you sell or gift it to anybody else, you are in legal trouble. Somebody is going to snitch, guaranteed.

+

Inject yourself

+

Syringes for injections

+

Syringes for injections - insulin syringes with permanently attached (fixed, integrated, non-detachable) needles 1/2" (12-13 mm) long, a new syringe every week or 10 days.
"Tuberculin" syringes with fixed needles 5/8" (16 mm) are available only in few mail-order stores in USA.

+

Needle gauge/diameter doesn't matter, drawing MCT oil through 30G takes one minute. Both U-100 and U-40 insulin syringes are suitable. Insulin syringes marketed for animals (veterinarian) are perfectly okay too.

+

If you discard an usual syringe with detachable needle after each injection then you lose 0.092 ml of the solution in the "dead space" in the socket between syringe and needle: http://lena.kiev.ua/deadspace.png , so a vial will last you 7 months instead of 10. Also, the socket can leak air which makes drawing seem impossible (tighten the socket with force and twist).

+

In most countries insulin syringes are available in most local pharmacies without prescription. Some pharmacists or pharmacy chains are holier than Pope, don't believe if few pharmacists claim prescription-only, just go to another pharmacy.

+

Or you can mail-order. Depending on country: USA: 1 2 3 4 5 (or search), Canada: 1 2 3 4 5 6 7 8 9, UK: 1 2 3 4, EU, France: 1 2 3 4, Netherlands: 1 2 3 4 5, Germany: 1 2 3, Switzerland, Italy: 1 2, Spain: 1 2, Denmark, Finland, Sweden, Mexico, Australia: 1 2, NZ: 1 2, Ukraine: 1 2 3 4 5, Russia: 1 2. Worldwide: 1 2 3 and on Amazon.

+

May be you heard the advice to use separate needles for drawing and injection because piercing the rubber stopper blunts the needle. Such advisers mistakenly exaggerate the blunting because it's easy to bend needle tip on hard glass ampule bottom while drawing from an all-glass single-dose ampule. Insulin syringes with non-detachable needles are designed for insulin vials also with rubber stoppers. However, if you are unusually sensitive to pain and willing to spend more money for small difference then you may follow this advice: buy 1 ml Luer Lock syringes, short needles 27G - 25G for drawing (thicker can damage the rubber stopper) and needles 1/2" - 5/8" (12-16 mm) 31G - 29G for injection. You'd lose 0.2 - 0.3 ml of the solution in all the dead spaces, but the solution you make yourself is cheap. Draw 0.05 - 0.1 ml more than you intend to inject because that much would be needed to fill the dead space in the hub of the injection needle. Attempts to expel the solution from the dead space by deliberately drawing a little air are mostly futile because capillary forces keep dead spaces filled.

+

Needle fright

+

If you are deadly afraid of needles (hey, I have instinctive fear of heights, so I understand) then buy an insulin syringe, lie down on your bed on your side (if you faint, no problem) and stick yourself with the empty syringe into the butt. If you manage that (possibly after several attempts), next times will be much easier.

+

As last resort, instead of estradiol enanthate you can buy micronized estradiol powder and take it orally 10 mg twice a day using 0.001 g scale. 40 g will last you 5 years, $2.5/month. How to take: find a small disposable plastic spoon, cut off the handle leaving a stub 2 cm long. Turn the scale on, wait for 0.000 , after that put the spoon at the center of the circle on the scale. Remember last two digits. Using the tweezers coming with the scale, put the powder into the spoon until weight increases for 0.009 - 0.011 g. Lick the powder off the spoon and swallow. Twice a day. Keep the powder in an emptied airtight jar from a cosmetic cream, covered from light with empty small tin can upside-down.

+

Or if you want slower changes.

+

Dosage

+

I recommend to inject 0.22 ml (22 units on U-100 insulin syringe scale or 8 units if U-40) weekly (on the same day of every week) or 0.31 ml every 10 days (on 1, 11, 21 of every month). The same dosage from the very beginning of MtF HRT and all the time later, post-op too, never stop. I chose this dosage to advise so that it's enough for complete suppression of testosterone production by testicles in any MtF. On the same dosage of the same hormone different people get trough blood estradiol level (just before next injection) differing in up to 10 times. Also, sensitivity of different people to the same level of the same hormone differs in times. Sensitivity is as important as levels. There isn't a test for sensitivity. So, why do doctors prescribe blood tests to MtF? Just to impress naive patients and to keep themselves busy and paid. For most MtF the dosage I advise is more than enough, but so what? It's laughably cheap. For a few this dosage is barely enough, so don't gamble and don't waste time. A few blood tests would be more expensive than all the hormone you'll ever take, so why bother?  Doctors love to tell bogeyman stories about side effects - just to scare you into blood tests and - paying them for more doctor visits.

+

If a doctor sees results of your blood tests, likely he'll claim "too much estradiol, dangerous". Then give him the link to a scientific article describing how doctors injected women with 4 times higher estradiol dosage than I advise, those women got blood estradiol level roughly 3000 pg/ml = 11000 pmol/l in average. Full text of that article can be accessed via Sci-Hub, or members of this [MTFHRT] group can read it here. I quote that article:

+
+

The treatment was well tolerated. No adverse effects were seen, the patients expressed a feeling of particular well being, 23% of them wanted to have the injections repeated and none of them wanted to stop treatment because of troubles or side effects.

+
+

That's on 4 times higher estradiol dosage than I advise.

+

How to inject

+

I recommend to inject into the upper outer quarter of a buttock into fat (subcutaneous) while lying on a bed on your side. It's the safest and least painful place. I advise against injecting into thigh because that can cause too fast absorption and faster blood estradiol level drop.

+

Take care to touch the needle to nothing except inner surface of needle cap, the skin at the place of injection and the rubber stopper of the vial.

+

There is an old tradition to disinfect skin (and the rubber stopper of the vial) with alcohol before an injection. Pharmacies sell alcohol-soaked swabs/wipes for that. However, this ritual is optional. World Health Organization says:

+
+

Wash skin that is visibly soiled or dirty. Swabbing of the clean skin before giving an injection is unnecessary. Swabbing of clean vial tops or ampoules with an antiseptic or disinfectant is unnecessary.

+
+

Also, you can read Introduction in a scientific article.

+

Anyway, even if you follow this ritual, don't wipe the needle because that would make it more dirty.

+

How to inject:
Lie down on a bed on your side. Injection will be into fat in the upper outer quarter of a buttock (exact place doesn't matter, fat layer in buttocks is thicker than needle length even in skinny people). Pull off the cap from the needle. Pull as much air into the syringe as you intend to inject. Pierce the center of the rubber stopper with the needle, inject the air into the vial. Turn so that the vial is at the top, syringe at the bottom. Pull the plunger to 0.1 ml more than you intend to inject (create vacuum in the syringe), hold and wait several minutes until the liquid very slowly seeps down and top surface of the liquid rises up to 0.08 ml mark on the scale. Push most of air bubbles and excess liquid back into the vial. Small air bubbles may remain, don't worry, injecting air bubbles is completely harmless. Pull the needle out, stick it into your butt (at about 90° angle) all the way in, inject (can take some time - speed doesn't matter). Pull out the needle, immediately press at the place of injection with a finger or a cotton wool pad/disc. While continuing to press, make a few circular motions (shift the skin, don't drag the finger across skin). Continue to press for 1 min. Cap the needle.

+

"Monitoring" unnecessary

+

If you begin your HRT from injectable estradiol as I describe here then likely in a few weeks you'll experience pain in breast buds (in many cases only at one side at first) like many cis-girls experience at puberty. The pain is not a sign of a problem and will last not forever.

+

Dosage I advise stops testosterone production by testicles as completely as surgical removal of testicles, but that will not rid you of the grey shade from shaven mustache and beard - a dead giveaway: you'll not pass until you complete needle electrolysis. Despite false advertising, laser and other hair removal methods using intense light in most cases remove facial hair temporarily, no matter how many sessions. Ignore this wisdom at your peril.

+

Any estradiol (E2) level between 300 and 5000 pg/ml (1100 - 18000 pmol/l) is okay for both pre-ops and post-ops. Estrone (E1) level doesn't matter. All doctors' assertions "too much" are bullshit meant to control us and extort money under guise of "care". The only reasonable cause to do a blood test for estradiol (once, at least a month after first injection, only on a day of next injection before it) is your peace of mind that you got indeed estradiol enanthate. But above I described two other ways to check that, and likely you'll experience pain in breast buds. I tested a new batch of estradiol enanthate powder on myself, my blood estradiol level was 1272 pg/ml = 4670 pmol/l 5 days after an injection. I had SRS in 1999, I needn't to suppress testosterone. Nevertheless, I don't intend to decrease my dosage. It slows down aging, on it I look and feel better.

+

Myths and what not to do

+

Above I explained about some myths and fallacies. Some more:

+

Myth: discard a vial 28 days after you began it. Bureaucrats get their salaries for inventing new rules, no matter how unreasonable. This rule was invented for hospitals with multiple patients (some with infectious diseases), not for your home.

+

If an average doctor prescribes injectable estradiol, he says nothing about needles, he says "inject into muscle" because the gospel (instructions sold with injectable estradiol) says so (without explanation why - really it's because the solvent used with EV sometimes causes allergy, then IM helps). You go to a pharmacy and ask for intramuscular injections. An average pharmacist asks you for injection volume (less than 1 ml) and sells you 2 ml syringes, each syringe comes with a needle in the same pack. Manufacturers put long needles with 10 ml syringes and shorter needles with 2 ml syringes. Why? Aesthetics. :-/ You get syringes with dead space and needles 25 mm long, you inject into buttock. You, pharmacist, nurse and doctor think that you inject into muscle. Really fat layer in buttocks is thicker even in very skinny people. You in fact inject into fat. And... it works. Gospels are full of fallacies.

+

Fallacy: after sticking the needle in your skin, you must aspirate to check whether you hit a blood vessel. There aren't significant blood vessels in buttocks at 13 mm (1/2") depth. If you aspirate, you wound yourself because of inevitable needle movements sideways.

+

Don't give a vial into the hands of a doctor, he'd destroy it. Doctors are jealous.

+

Don't use an emulator (calculator of blood levels). It uses average statistical data, but you are not a statistically average person.

+

Myth: begin from pills (low dosage), then after some time switch to injections. Doctors love to begin from low dosage because that keeps them busy and paid. So they invent explanations why it's allegedly better. People repeat doctor claims.

+

Myth: decrease estrogen dosage post-op. Estrogen dosages described in pharmaceutical reference books (collections of package inserts) for men with prostatic cancer are higher (designed to suppress testosterone production by testicles) than for women (after menopause) - limited in the fear of uterine cancer. Only after SRS we magically become women in doctors' eyes.

+

Myth: "estrogens" increase risk of blood clots, take Aspirin to counteract that. Ethinylestradiol increases risk of venous thrombosis, Aspirin decreases risk of arterial thrombosis in coronal arteries in the heart. Combination of ethinylestradiol with Aspirin is like wearing a flak jacket while going against a gas attack. Don't confuse ethinylestradiol (EE) with estradiol enanthate (EEn). Unlike ethinylestradiol, injectable estradiol practically doesn't affect risk of thrombosis. Did you know that thrombosis risk depends (among other things) on whether your blood is type 0(1) or any other type ("non-zero")? Estradiol enanthate dosage I advise affects blood clotting less.

+

Fallacy: stop "hormones" some time before SRS or another surgery, resume only some time later. Surgeons don't know and don't want to know differences between various estrogens and routes of their delivery. Ethinylestradiol in combination with bloodflow in immobile legs stopped by stirrups (to move legs out of surgeon's way during SRS) can cause deep vein thrombosis and deadly pulmonary embolism as a consequence. Don't try to explain to the surgeon that injectable estradiol doesn't do that, tell that you comply but silently continue injections for your passability and mood not to worsen. Blood tests surgeons require check some blood clotting parameters, not estradiol.

+

Schizophrenic delusion: Chinese companies have been known to mix Ethinyl Estradiol into their hormone powders as a cheap way to boost efficacy. The only way for end-users to check efficacy is an usual blood test for estradiol level which ignores ethinylestradiol completely. Therefore, only a schizophrenic (literally) could produce this raving.

+

Myth: libido and erections are signs of testosterone. In many MtF estradiol dosage I advise stimulates libido and erections though suppresses testosterone production by testicles completely. If still in doubt, do a blood test for testosterone on a day of next injection before it. Cis-women (and post-SRS MtF) get erections of clitoris - exactly same mechanism as erections of penis.

+

Myth: excess estrogen is converted to testosterone. The conversion estrone<->estradiol is bidirectional, but the conversion testosterone->estradiol is strictly unidirectional.

+

Myth: if you take too much estradiol then SHBG will bind it and make it unusable. If estradiol level increases, liver produces more SHBG. Nevertheless, free estradiol level increases too.

+

I explained a misunderstanding about steam sterilization separately because the explanation is lengthy and requires some physics knowledge.

+

Words "estrogen dominance" were invented by marketers of progesterone and quackeries they call progesterone bla-bla-something like "Wild Yam". Long ago progesterone was produced chemically from wild yam, but human body cannot perform that chemical conversion.

+

If you are wondering about real progesterone:

+

1) Injectable progesterone is very short-living, must be injected daily. Oral progesterone is ineffective because most of it is converted to allopregnanolone which common blood tests confuse with progesterone. Hydroxyprogesterone caproate is not bioidentical, it's not converted in the body to progesterone (unlike estradiol valerate and estradiol enanthate).

+

2) Progesterone decreases rate of synthesis of estrogen receptors. Cis-women are supposed to benefit from that, but goals of MtF are opposite.

+

3) Estradiol develops ducts in milk glands, progesterone develops alveoles. Most of breast volume is ducts and connective tissue between them. If an alveole formed (at the end of a duct), that duct will not grow in length anymore. So, progesterone can stunt breast growth. Cyproterone acetate too, it's a strong progestogen.

+

I advise not to add progesterone for at least 3 years since starting estradiol injections at least 40 mg/month (not since the very beginning of HRT). Or never add progesterone. Though progesterone is a female hormone, that doesn't mean that it's beneficial for MtF (no uterus).

+

Myth: an article linked from Wikipedia claimed a case of prolactinoma as a side effect of estradiol enanthate. Actually factory-made injections with estradiol enanthate always contain also high dosage of a progestin. Cyproterone acetate is a strong progestin and is known to cause prolactinoma. One more reason to never add progesterone if you haven't an uterus.

+

Myth: compounding pharmacies make superior products. If you get exceptionally lucky and find a doctor willing to prescribe as high injectable estradiol dosage as I advise who doesn't freak out at blood test results (you'd have to pay to gatekeeprs, doctor, pharmacy and labs), compounding pharmacies in few countries can cook injectable estradiol with prescription. No compounding pharmacy would have estradiol enanthate powder, and I doubt that they can make estradiol cypionate (EC) 50 mg/ml because factory-made EC is 5 mg/ml max. They cannot make more than 10 mg/ml without solvent (benzyl benzoate) which can cause allergy. They use other oils which also cause allergy more often than MCT oil. But the main their problem is that they never mix in each vial separately and often repeat Indian factories' mistake I described above: undissolved powder gets stuck in a filter, so you get much less estradiol than prescribed (often happens in Canada). Another example of their stupidity: a compounding ("Galenic") pharmacy in Italy used ethoxylated Castor oil (essentially a soap) instead of plain Castor oil, so of course injections hurt immensely and were ineffective. If you want it done right, Do It Yourself.

+
+

Another my how-to: voice.

+

Lena

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/29602/history.html b/groups.io/g/MTFHRT/wiki/29602/history.html index 3b53ab89..5d1df61a 100644 --- a/groups.io/g/MTFHRT/wiki/29602/history.html +++ b/groups.io/g/MTFHRT/wiki/29602/history.html @@ -6,7 +6,7 @@ - + @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774617.1713918440372075712"); + console.log("client_id:", "web.web09.236708.1714523380298758175"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774617.1713918440372075712" + client_id: "web.web09.236708.1714523380298758175" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { - + - - + + @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -576,13 +901,47 @@ function createAlert(msg, isError, autoClose, noClose) { <tr> <td> - <input type=checkbox name="dataid" id="203230" value="203230" onclick="countChecked('203230')" + <input type=checkbox name="dataid" id="204015" value="204015" onclick="countChecked('204015')" checked> + <a href="https://groups.io/g/MTFHRT/profile/@Lena">Lena</a> + + + + </td> + <td> + <a href="204015.html"> + + + + Updated Ultimate DIY page + + + </a> + </td> + <td> + +<script id="timedispwdataupdated204015"> + $('#timedispwdataupdated204015').replaceWith(DisplayShortTime(1714463966218418632, false + )); +</script> + + </td> + </tr> + + <tr> + <td> + <input type=checkbox name="dataid" id="203230" value="203230" onclick="countChecked('203230')" + > + + + + + <a href="https://groups.io/g/MTFHRT/profile/@Lena">Lena</a> @@ -7797,7 +8156,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165842.html"> + <a href="165842"> @@ -7831,7 +8190,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165840.html"> + <a href="165840"> @@ -7865,7 +8224,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165830.html"> + <a href="165830"> @@ -7899,7 +8258,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165664.html"> + <a href="165664"> @@ -7933,7 +8292,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165530.html"> + <a href="165530"> @@ -7967,7 +8326,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165470.html"> + <a href="165470"> @@ -8001,7 +8360,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165469.html"> + <a href="165469"> @@ -8035,7 +8394,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165467.html"> + <a href="165467"> @@ -8069,7 +8428,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165437.html"> + <a href="165437"> @@ -8103,7 +8462,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165250.html"> + <a href="165250"> @@ -8137,7 +8496,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165219.html"> + <a href="165219"> @@ -8171,7 +8530,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="165198.html"> + <a href="165198"> @@ -9591,6 +9950,10 @@ function createAlert(msg, isError, autoClose, noClose) { </form> <script type="text/javascript"> +contentLoaded(false, function() { + + UpdateSidebar("wiki"); +}); function countChecked(id) { var checkedVal = 0; @@ -9617,20 +9980,20 @@ function countChecked(id) { } </script> + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -9640,9 +10003,7 @@ function countChecked(id) { </div> </div> - - @@ -9671,48 +10032,43 @@ function countChecked(id) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -9727,13 +10083,17 @@ function countChecked(id) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -9755,7 +10115,7 @@ function countChecked(id) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -9776,138 +10136,144 @@ function countChecked(id) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -9929,6 +10295,21 @@ function countChecked(id) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30843.html b/groups.io/g/MTFHRT/wiki/30843.html index 1820895d..6e51d1e5 100644 --- a/groups.io/g/MTFHRT/wiki/30843.html +++ b/groups.io/g/MTFHRT/wiki/30843.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774508.1713918438333288990"); + console.log("client_id:", "web.web09.236574.1714523377527203207"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774508.1713918438333288990" + client_id: "web.web09.236574.1714523377527203207" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Basic Estrogel Guide</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Basic Estrogel Guide</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,6 +927,50 @@ function createAlert(msg, isError, autoClose, noClose) { + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> + <div class="btn-group"> + <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + Pages + <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + + <li> + <a href="30843.html"> + Basic Estrogel Guide + </a> + </li> + + <li> + <a href="30846.html"> + Home + </a> + </li> + + <li> + <a href="32288.html"> + How to measure melting point of most organic powders using typical household items. + </a> + </li> + + <li> + <a href="34293.html"> + steam sterilization + </a> + </li> + + <li> + <a href="29602.html"> + Ultimate DIY + </a> + </li> + + </ul> + </div> + + </span> <div class="pull-right"> @@ -616,15 +988,14 @@ function createAlert(msg, isError, autoClose, noClose) { <i class="fa fa-link fa-lg"></i> </a> </div> - <p> -   - </p> - <br> + </div> + </div> + <div class="row"> <div class="col-sm-12"> - <span class="visitedlinks"> + <span class="wikidisplay user-content"> <h1>DIY Estrogel Guide</h1> <p>This guide will instruct you on the materials and tools needed for home DIY basic estrogel compounding. There are easier methods out there, such as mixing estradiol into pre-made hand sanitizers, but this is for those who would prefer to compound their own gels, or manufacture at a scale where buying hand sanitizer is cost prohibitive. There are also some concerns about hand sanitizer formulations containing denaturing agents or other additives that might be bad for transdermal drug delivery. If you are interested in more experimental gel formulations or ones based on hand sanitizer, you can check out reddit.com/r/estrogel/wiki, which is where I got most of this information. <br/><br/>With this guide, you can produce supersaturated estrogels that are suitable for high-dose estradiol monotherapy. This is a great alternative to injections for the needle-shy or paranoid. <br/><br/>This recipe is based off of a patent that includes a generic estrogel recipe, available here: <a href="https://patents.google.com/patent/US20070154533A1/en" target="_blank" rel="nofollow noopener">https://patents.google.com/patent/US20070154533A1/en</a> - page 39 of the PDF has the recipe. This recipe has been adjusted for higher concentrations and higher absorption, using 60% ethanol, which is known to have the best absorption for estradiol. (<a href="https://sci-hub.se/https://doi.org/10.1016/j.addr.2012.09.032" target="_blank" rel="nofollow noopener">https://sci-hub.se/https://doi.org/10.1016/j.addr.2012.09.032</a>)</p> <p> </p> @@ -683,66 +1054,30 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="row"> <div class="col-sm-12"> - <div class="hidden-print"> - <div class="btn-group"> - <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> - Pages - <span class="caret"></span> - </button> - <ul class="dropdown-menu" role="menu"> - - <li> - <a href="30843.html"> - Basic Estrogel Guide - </a> - </li> - - <li> - <a href="30846.html"> - Home - </a> - </li> - - <li> - <a href="32288.html"> - How to measure melting point of most organic powders using typical household items. - </a> - </li> - - <li> - <a href="34293.html"> - steam sterilization - </a> - </li> - - <li> - <a href="29602.html"> - Ultimate DIY - </a> - </li> - - </ul> - </div> - - </div> </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -752,9 +1087,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -783,48 +1116,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -839,13 +1167,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -867,7 +1199,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -888,138 +1220,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1041,6 +1379,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30843/171363.html b/groups.io/g/MTFHRT/wiki/30843/171363.html new file mode 100644 index 00000000..a4c042e7 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/30843/171363.html @@ -0,0 +1,1403 @@ + + + <!DOCTYPE html> + <html lang="en-US"> + <head> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <meta name="pinterest" content="nopin" /> + <meta name="pinterest" content="nohover" /> + + <meta name="3778517eb4810dfb5d143ed8f1b359b3b5a82923" content="0f56257c3db4a222e91b11bc6871c4df2e263b28" /> + <link rel="apple-touch-icon" sizes="57x57" href="https://groups.io/img/org.1/favicons/apple-icon-57x57.png"> + <link rel="apple-touch-icon" sizes="60x60" href="https://groups.io/img/org.1/favicons/apple-icon-60x60.png"> + <link rel="apple-touch-icon" sizes="72x72" href="https://groups.io/img/org.1/favicons/apple-icon-72x72.png"> + <link rel="apple-touch-icon" sizes="76x76" href="https://groups.io/img/org.1/favicons/apple-icon-76x76.png"> + <link rel="apple-touch-icon" sizes="114x114" href="https://groups.io/img/org.1/favicons/apple-icon-114x114.png"> + <link rel="apple-touch-icon" sizes="120x120" href="https://groups.io/img/org.1/favicons/apple-icon-120x120.png"> + <link rel="apple-touch-icon" sizes="144x144" href="https://groups.io/img/org.1/favicons/apple-icon-144x144.png"> + <link rel="apple-touch-icon" sizes="152x152" href="https://groups.io/img/org.1/favicons/apple-icon-152x152.png"> + <link rel="apple-touch-icon" sizes="180x180" href="https://groups.io/img/org.1/favicons/apple-icon-180x180.png"> + <link rel="icon" type="image/png" sizes="192x192" href="../../../../img/org.1/favicons/android-icon-192x192.png"> + <link rel="icon" type="image/png" sizes="32x32" href="../../../../img/org.1/favicons/favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="96x96" href="../../../../img/org.1/favicons/favicon-96x96.png"> + <link rel="icon" type="image/png" sizes="16x16" href="../../../../img/org.1/favicons/favicon-16x16.png"> + <link rel="manifest" href="../../../../img/org.1/favicons/manifest.json"> + <meta name="msapplication-TileColor" content="#ffffff"> + <meta name="msapplication-TileImage" content="/ms-icon-144x144.png"> + + + + +<script> +/* stubs */ +const hapticsImpactHeavy = async () => { +}; +const hapticsImpactMedium = async () => { +}; +const hapticsImpactLight = async () => { +}; +const hapticsVibrate = async () => { +}; +const hapticsSelectionStart = async () => { +}; +const hapticsSelectionChanged = async () => { +}; +const hapticsSelectionEnd = async () => { +}; +</script> + + +<script> + + function setPullToRefresh() {} + + function gotoURL(inurl) { + window.location.href = inurl; + return; + } + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); + if (isHTMX == true) { + document.body.addEventListener('htmx:afterSettle', f, {once: true}); + } else { + if (document.readyState !== 'loading') { + console.log('document is already ready, just execute code here'); + f(); + } else { + console.log('document was not ready, place code here'); + document.addEventListener('DOMContentLoaded', f, {once: true}); + } + } + } + + // stub + function logError(data, url, linenumber) { + console.log(data) + return; + } + var pushSubToken; + var ignoreErrors = false; + var lastError = ""; + + window.onerror = function(errorMessage, errorUrl, errorLine, errorColumn, errorObj) { + let column; + let stack; + if (console && console.log) { + console.log("msg:", errorMessage); + console.log("url:", errorUrl); + console.log("line:", errorLine); + if (errorColumn !== undefined && errorObj != null) { + console.log("column:", errorColumn); + column = errorColumn; + } + if (errorObj !== undefined && errorObj != null) { + console.log("stack:", errorObj.stack); + stack = errorObj.stack; + } + console.log("client_id:", "web.web09.236766.1714523381494281849"); + console.log("last_error:", lastError); + console.log("stack:", stack); + } + if (errorUrl == "" || errorUrl === null) { + errorUrl = window.location.href; + } + if (errorMessage.includes("SecurityError:") == true) { + ignoreErrors = true; + } + if (ignoreErrors == true) { + console.log("cookies, disabled, ignoring"); + lastError = errorMessage; + return; + } + jQuery.ajax({ + type: 'POST', + url: '/jsclienterror', + data: { + msg: errorMessage, + url: errorUrl, + line: errorLine, + column: column, + stack: stack, + last_error: lastError, + client_id: "web.web09.236766.1714523381494281849" + }, + success: function() { + if (console && console.log) { + console.log('JS error report successful.'); + } + lastError = errorMessage; + }, + error: function() { + if (console && console.error) { + console.error('JS error report submission failed!'); + } + lastError = errorMessage; + } + }); + return true; + } + +</script> + + + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> + <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> + <script src="../../../../js/run_prettify.js"></script> + <title> + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

DIY Estrogel Guide

+

 

+


This guide will instruct you on the materials and tools needed for home DIY basic estrogel compounding. There are easier methods out there, such as mixing estradiol into pre-made hand sanitizers, but this is for those who would prefer to compound their own gels, or manufacture at a scale where buying hand sanitizer is cost prohibitive. There are also some concerns about hand sanitizer formulations containing denaturing agents or other additives that might be bad for transdermal drug delivery. If you are interested in more experimental gel formulations or ones based on hand sanitizer, you can check out reddit.com/r/estrogel/wiki, which is where I got most of this information.

With this guide, you can produce supersaturated estrogels that are suitable for high-dose estradiol monotherapy. This is a great alternative to injections for the needle-shy or paranoid.

This recipe is based off of a patent that includes a generic estrogel recipe, available here: https://patents.google.com/patent/US20070154533A1/en - page 39 of the PDF has the recipe. This recipe has been adjusted for higher concentrations and higher absorption, using 60% ethanol, which is known to have the best absorption for estradiol. (https://sci-hub.se/https://doi.org/10.1016/j.addr.2012.09.032)



+

Sourcing Estradiol

+

The sources for estradiol are much the same as DIY injections, so I won't go into detail here. Look on made-in-china.com and search for 17b-estradiol, or more specifically, CAS number 50-28-2. For a single person, assuming they are doing monotherapy at 1-2mg a day, a typical yearly consumption is half a gram. This means 50 grams is enough to last you 100 years. I got 100 grams for $200 shipped from Hubei Vanz. You want 17 beta estradiol, not estradiol valerate, cypionate, enanthate, etc. 





+

Other ingredients

+

Other ingredients, including the quantity and price I got them before, are listed below.

+
    +
  • Carbomer/Carbopol 980 x 120g - $25 - amazon, ebay, cosmetic supply, aliexpress
  • +
  • Triethanolamine x 250ml - $20 - amazon, ebay, cosmetic supply
  • +
  • Distilled Water - $2-3 from your local grocery store
  • +
  • 95% (190 proof) grain alcohol, such as everclear - 750 ml - $20 - liquor store (any alcohol over 60%/120 proof is okay)
  • +
+

Tools

+
    +
  • Coffee frother wand - $5-10 on ebay, aliexpress, amazon. The longer and narrower the better.
  • +
  • Airless pump dispenser bottles - I have used this style(https://m.media-amazon.com/images/I/51D0UnNSu+L._SL1500_.jpg) in the past because one pump = 225mg which is roughly equivalent to .5mg of estradiol (at .24% concentration). This works out well for me because it means two pumps a day is enough for monotherapy. It also means 1 80 ml bottle (80 ml is just under the 3 oz limit on airplanes) is enough to last me roughly a month. These might not be the easiest pumps to work with though, but more on that later.
  • +
  • 100ml syringes with cap (like these https://www.amazon.com/100ml-Syringe-s-Caps-Industrial-Scientific/dp/B086H7TC1T) - also might not be necessary, more on that later
  • +
  • milligram scale such as the gemini-20 - $20-30
  • +
  • mixing container of some kind, such as a mason jar, glass cup, beaker, etc.
  • +
  • optional - metal stirrers and weighing spatulas such as these: https://www.amazon.com/gp/product/B07HHWCNB9/ - $10

  • +
+

Total: I spent about $350 to get started, but you can get everything much cheaper if you are willing to shop around and buy small quantities. The amount of carbomer, estradiol, triethanolamine, etc. per bottle is very little, so even small amounts will last you a long time. If you spent what I did, raw materials alone (not counting tools) and the pump bottle is about $5-10 per bottle. The most expensive components for me are ethanol and airless pumps. Buying airless pumps in bulk from alibaba or made-in-china sellers can get prices down lower, I know some also try using 99% isopropyl alcohol instead of ethanol, though I haven't tried this. One 80ml bottle will last you about a month at .5mg a day @ .24% concentration.

+

Preparation of gel

+

Gel preparation is quite simple, first you need to find out how much alcohol and water you need. You are trying to reach a concentration of 60/40 ethanol to water. You can easily find out how much water you need to reach an overall concentration of 60%(by volume). You can easily find online calculators for this, such as here: https://ezcalc.me/alcohol-dilution-calculator/. Assuming you want to make 100ml of gel, for example, and have 95%(190 proof) grain alcohol, you'll need ~63ml of 95% ethanol and 37ml of distilled water. From here on out I will assume you want 100ml of gel and have 95% ethanol.

+

 

+

Recipe

+

63ml ethanol
37ml distilled water
1g Carbomer 980
1.35g Triethanolamine
Estradiol to your desired concentration, I usually do .24%(by weight of the entire solution, accounting for the density of 95% ethanol at ~.8g/ml), which comes to ~215mg.

+

 

+

Procedure

+
    +
  1. Pour the ethanol into a mixing container, such as a beaker or jar.
  2. +
  3. Weigh your estradiol on a weighing paper, weighing boat, or a piece of tinfoil with your weighing spatulas, or another instrument.
  4. +
  5. Dissolve your estradiol into your ethanol and stir with a stirring instrument or coffee frother. Your solution should be clear, without any undissolved material.
  6. +
  7. Add water and stir.
  8. +
  9. Add Carbomer 980, and mix with coffee frother. This can take a long time to dissolve completely. I usually stir it with the coffee frother until most of it dissolves, then I let the solution sit while covered for 20 minutes. Then, I come back and stir it again until there are no clumps or undissolved powder.
  10. +
  11. Remove plunger from 100ml syringe. Twist on luer lock cap.
  12. +
  13. Transfer gel solution into your 100ml syringe, from the plunger side.
  14. +
  15. Add triethanolamine to your solution, stirring with your coffee frother. The solution will now go from liquid to a thicker gel, much like hand sanitizer. Stir extremely thoroughly and try to distribute the triethanolamine throughout the entire solution.
  16. +
  17. Insert plunger into back of syringe and remove the luer lock cap.
  18. +
  19. Use syringe to dispense gel into your airless pump of choice. You may want to stop a few times to let the gel settle to avoid huge air bubbles. You can tap the bottom of the airless pump against a hard surface to make the gel settle.
  20. +
+

 

+

Potential improvements and challenges

+

The hardest part of this procedure is working with the gel after triethanolamine has been added, as it almost immediately becomes very thick, clumpy, sticky, etc. You do not want to add triethanolamine to the gel before it is either in its final container, or in a syringe. If you add triethanolamine in the mixing container, it will be extremely difficult to transfer. If you get airless pumps of this style: https://www.aliexpress.com/item/2251832632413742.html you may be able to add the triethanolamine to the solution after it's already in the pump, however the mouth needs to be wide enough to fit your coffee frother. You need to be able to thoroughly mix the triethanolamine so that it can neutralize the pH of the carbomer 980. I haven't tried these bottles, but I have some other candidates on order and will update if I find a better bottle.

One possible area of improvement is adding a penetration enhancer, such as oleic acid, d-limonene, or isopropyl myristate. I personally experimented with 2% isopropyl myristate but found it incredibly irritating to my skin, and made the gel burn really badly. It also fell out of solution in my pump bottle. Personally, I just apply the gel scrotally, which results in extremely high absorption, so I feel no need to use penetration enhancers.

+

 

+

Usage/my results

+

With the bottles I recommend, each pump will dispense about 225mg of gel, or .5mg per pump. I used 4 pumps a day at first, putting 1 pump on my scrotum, and 1 on my thigh, morning and night, and after a month of this, I had the following blood test results:
Testosterone: 29 ng/dL
Estradiol: 326 pg/mL

I am currently lowering my dose to 2 pumps a day, on the scrotum only, to see if 1mg scrotally is enough for monotherapy. I will report back once I have blood test results. Although conventional wisdom with transdermal delivery says that transdermal gels have a depot effect, scrotal application has not been studied much and it could be the case that absorption is much quicker, so to be safe I apply twice a day rather than using 2 pumps once a day, and I also get my blood tests done at trough (before I do my morning dose).

This is a promising alternative to injections, and because it's alcohol based, the risk of contamination is low, even without a clean room or heat sterilization. This is also a great alternative for those who are needle-phobic or are for some reason not wanting to do injections.

If I can answer any questions, please feel free to reach out to me at owl@owl.haus or on discord: allie castro#1234

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/30843/171364.html b/groups.io/g/MTFHRT/wiki/30843/171364.html new file mode 100644 index 00000000..e430de1e --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/30843/171364.html @@ -0,0 +1,1403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

DIY Estrogel Guide

+

This guide will instruct you on the materials and tools needed for home DIY basic estrogel compounding. There are easier methods out there, such as mixing estradiol into pre-made hand sanitizers, but this is for those who would prefer to compound their own gels, or manufacture at a scale where buying hand sanitizer is cost prohibitive. There are also some concerns about hand sanitizer formulations containing denaturing agents or other additives that might be bad for transdermal drug delivery. If you are interested in more experimental gel formulations or ones based on hand sanitizer, you can check out reddit.com/r/estrogel/wiki, which is where I got most of this information.

With this guide, you can produce supersaturated estrogels that are suitable for high-dose estradiol monotherapy. This is a great alternative to injections for the needle-shy or paranoid.

This recipe is based off of a patent that includes a generic estrogel recipe, available here: https://patents.google.com/patent/US20070154533A1/en - page 39 of the PDF has the recipe. This recipe has been adjusted for higher concentrations and higher absorption, using 60% ethanol, which is known to have the best absorption for estradiol. (https://sci-hub.se/https://doi.org/10.1016/j.addr.2012.09.032)

+

 

+

Sourcing Estradiol

+

The sources for estradiol are much the same as DIY injections, so I won't go into detail here. Look on made-in-china.com and search for 17b-estradiol, or more specifically, CAS number 50-28-2. For a single person, assuming they are doing monotherapy at 1-2mg a day, a typical yearly consumption is half a gram. This means 50 grams is enough to last you 100 years. I got 100 grams for $200 shipped from Hubei Vanz. You want 17 beta estradiol, not estradiol valerate, cypionate, enanthate, etc. 





+

Other ingredients

+

Other ingredients, including the quantity and price I got them before, are listed below.

+
    +
  • Carbomer/Carbopol 980 x 120g - $25 - amazon, ebay, cosmetic supply, aliexpress
  • +
  • Triethanolamine x 250ml - $20 - amazon, ebay, cosmetic supply
  • +
  • Distilled Water - $2-3 from your local grocery store
  • +
  • 95% (190 proof) grain alcohol, such as everclear - 750 ml - $20 - liquor store (any alcohol over 60%/120 proof is okay)
  • +
+

Tools

+
    +
  • Coffee frother wand - $5-10 on ebay, aliexpress, amazon. The longer and narrower the better.
  • +
  • Airless pump dispenser bottles - I have used this style(https://m.media-amazon.com/images/I/51D0UnNSu+L._SL1500_.jpg) in the past because one pump = 225mg which is roughly equivalent to .5mg of estradiol (at .24% concentration). This works out well for me because it means two pumps a day is enough for monotherapy. It also means 1 80 ml bottle (80 ml is just under the 3 oz limit on airplanes) is enough to last me roughly a month. These might not be the easiest pumps to work with though, but more on that later.
  • +
  • 100ml syringes with cap (like these https://www.amazon.com/100ml-Syringe-s-Caps-Industrial-Scientific/dp/B086H7TC1T) - also might not be necessary, more on that later
  • +
  • milligram scale such as the gemini-20 - $20-30
  • +
  • mixing container of some kind, such as a mason jar, glass cup, beaker, etc.
  • +
  • optional - metal stirrers and weighing spatulas such as these: https://www.amazon.com/gp/product/B07HHWCNB9/ - $10

  • +
+

Total: I spent about $350 to get started, but you can get everything much cheaper if you are willing to shop around and buy small quantities. The amount of carbomer, estradiol, triethanolamine, etc. per bottle is very little, so even small amounts will last you a long time. If you spent what I did, raw materials alone (not counting tools) and the pump bottle is about $5-10 per bottle. The most expensive components for me are ethanol and airless pumps. Buying airless pumps in bulk from alibaba or made-in-china sellers can get prices down lower, I know some also try using 99% isopropyl alcohol instead of ethanol, though I haven't tried this. One 80ml bottle will last you about a month at .5mg a day @ .24% concentration.

+

Preparation of gel

+

Gel preparation is quite simple, first you need to find out how much alcohol and water you need. You are trying to reach a concentration of 60/40 ethanol to water. You can easily find out how much water you need to reach an overall concentration of 60%(by volume). You can easily find online calculators for this, such as here: https://ezcalc.me/alcohol-dilution-calculator/. Assuming you want to make 100ml of gel, for example, and have 95%(190 proof) grain alcohol, you'll need ~63ml of 95% ethanol and 37ml of distilled water. From here on out I will assume you want 100ml of gel and have 95% ethanol.

+

 

+

Recipe

+

63ml ethanol
37ml distilled water
1g Carbomer 980
1.35g Triethanolamine
Estradiol to your desired concentration, I usually do .24%(by weight of the entire solution, accounting for the density of 95% ethanol at ~.8g/ml), which comes to ~215mg.

+

 

+

Procedure

+
    +
  1. Pour the ethanol into a mixing container, such as a beaker or jar.
  2. +
  3. Weigh your estradiol on a weighing paper, weighing boat, or a piece of tinfoil with your weighing spatulas, or another instrument.
  4. +
  5. Dissolve your estradiol into your ethanol and stir with a stirring instrument or coffee frother. Your solution should be clear, without any undissolved material.
  6. +
  7. Add water and stir.
  8. +
  9. Add Carbomer 980, and mix with coffee frother. This can take a long time to dissolve completely. I usually stir it with the coffee frother until most of it dissolves, then I let the solution sit while covered for 20 minutes. Then, I come back and stir it again until there are no clumps or undissolved powder.
  10. +
  11. Remove plunger from 100ml syringe. Twist on luer lock cap.
  12. +
  13. Transfer gel solution into your 100ml syringe, from the plunger side.
  14. +
  15. Add triethanolamine to your solution, stirring with your coffee frother. The solution will now go from liquid to a thicker gel, much like hand sanitizer. Stir extremely thoroughly and try to distribute the triethanolamine throughout the entire solution.
  16. +
  17. Insert plunger into back of syringe and remove the luer lock cap.
  18. +
  19. Use syringe to dispense gel into your airless pump of choice. You may want to stop a few times to let the gel settle to avoid huge air bubbles. You can tap the bottom of the airless pump against a hard surface to make the gel settle.
  20. +
+

 

+

Potential improvements and challenges

+

The hardest part of this procedure is working with the gel after triethanolamine has been added, as it almost immediately becomes very thick, clumpy, sticky, etc. You do not want to add triethanolamine to the gel before it is either in its final container, or in a syringe. If you add triethanolamine in the mixing container, it will be extremely difficult to transfer. If you get airless pumps of this style: https://www.aliexpress.com/item/2251832632413742.html you may be able to add the triethanolamine to the solution after it's already in the pump, however the mouth needs to be wide enough to fit your coffee frother. You need to be able to thoroughly mix the triethanolamine so that it can neutralize the pH of the carbomer 980. I haven't tried these bottles, but I have some other candidates on order and will update if I find a better bottle.

One possible area of improvement is adding a penetration enhancer, such as oleic acid, d-limonene, or isopropyl myristate. I personally experimented with 2% isopropyl myristate but found it incredibly irritating to my skin, and made the gel burn really badly. It also fell out of solution in my pump bottle. Personally, I just apply the gel scrotally, which results in extremely high absorption, so I feel no need to use penetration enhancers.

+

 

+

Usage/my results

+

With the bottles I recommend, each pump will dispense about 225mg of gel, or .5mg per pump. I used 4 pumps a day at first, putting 1 pump on my scrotum, and 1 on my thigh, morning and night, and after a month of this, I had the following blood test results:
Testosterone: 29 ng/dL
Estradiol: 326 pg/mL

I am currently lowering my dose to 2 pumps a day, on the scrotum only, to see if 1mg scrotally is enough for monotherapy. I will report back once I have blood test results. Although conventional wisdom with transdermal delivery says that transdermal gels have a depot effect, scrotal application has not been studied much and it could be the case that absorption is much quicker, so to be safe I apply twice a day rather than using 2 pumps once a day, and I also get my blood tests done at trough (before I do my morning dose).

This is a promising alternative to injections, and because it's alcohol based, the risk of contamination is low, even without a clean room or heat sterilization. This is also a great alternative for those who are needle-phobic or are for some reason not wanting to do injections.

If I can answer any questions, please feel free to reach out to me at owl@owl.haus or on discord: allie castro#1234

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/30843/171365.html b/groups.io/g/MTFHRT/wiki/30843/171365.html new file mode 100644 index 00000000..401532f9 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/30843/171365.html @@ -0,0 +1,1403 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

DIY Estrogel Guide

+

This guide will instruct you on the materials and tools needed for home DIY basic estrogel compounding. There are easier methods out there, such as mixing estradiol into pre-made hand sanitizers, but this is for those who would prefer to compound their own gels, or manufacture at a scale where buying hand sanitizer is cost prohibitive. There are also some concerns about hand sanitizer formulations containing denaturing agents or other additives that might be bad for transdermal drug delivery. If you are interested in more experimental gel formulations or ones based on hand sanitizer, you can check out reddit.com/r/estrogel/wiki, which is where I got most of this information.

With this guide, you can produce supersaturated estrogels that are suitable for high-dose estradiol monotherapy. This is a great alternative to injections for the needle-shy or paranoid.

This recipe is based off of a patent that includes a generic estrogel recipe, available here: https://patents.google.com/patent/US20070154533A1/en - page 39 of the PDF has the recipe. This recipe has been adjusted for higher concentrations and higher absorption, using 60% ethanol, which is known to have the best absorption for estradiol. (https://sci-hub.se/https://doi.org/10.1016/j.addr.2012.09.032)

+

 

+

Sourcing Estradiol

+

The sources for estradiol are much the same as DIY injections, so I won't go into detail here. Look on made-in-china.com and search for 17b-estradiol, or more specifically, CAS number 50-28-2. For a single person, assuming they are doing monotherapy at 1-2mg a day, a typical yearly consumption is half a gram. This means 50 grams is enough to last you 100 years. I got 100 grams for $200 shipped from Hubei Vanz. You want 17 beta estradiol, not estradiol valerate, cypionate, enanthate, etc. 

+


Other ingredients

+

Other ingredients, including the quantity and price I got them before, are listed below.

+
    +
  • Carbomer/Carbopol 980 x 120g - $25 - amazon, ebay, cosmetic supply, aliexpress
  • +
  • Triethanolamine x 250ml - $20 - amazon, ebay, cosmetic supply
  • +
  • Distilled Water - $2-3 from your local grocery store
  • +
  • 95% (190 proof) grain alcohol, such as everclear - 750 ml - $20 - liquor store (any alcohol over 60%/120 proof is okay)
  • +
+

Tools

+
    +
  • Coffee frother wand - $5-10 on ebay, aliexpress, amazon. The longer and narrower the better.
  • +
  • Airless pump dispenser bottles - I have used this style(https://m.media-amazon.com/images/I/51D0UnNSu+L._SL1500_.jpg) in the past because one pump = 225mg which is roughly equivalent to .5mg of estradiol (at .24% concentration). This works out well for me because it means two pumps a day is enough for monotherapy. It also means 1 80 ml bottle (80 ml is just under the 3 oz limit on airplanes) is enough to last me roughly a month. These might not be the easiest pumps to work with though, but more on that later.
  • +
  • 100ml syringes with cap (like these https://www.amazon.com/100ml-Syringe-s-Caps-Industrial-Scientific/dp/B086H7TC1T) - also might not be necessary, more on that later
  • +
  • milligram scale such as the gemini-20 - $20-30
  • +
  • mixing container of some kind, such as a mason jar, glass cup, beaker, etc.
  • +
  • optional - metal stirrers and weighing spatulas such as these: https://www.amazon.com/gp/product/B07HHWCNB9/ - $10

  • +
+

Total: I spent about $350 to get started, but you can get everything much cheaper if you are willing to shop around and buy small quantities. The amount of carbomer, estradiol, triethanolamine, etc. per bottle is very little, so even small amounts will last you a long time. If you spent what I did, raw materials alone (not counting tools) and the pump bottle is about $5-10 per bottle. The most expensive components for me are ethanol and airless pumps. Buying airless pumps in bulk from alibaba or made-in-china sellers can get prices down lower, I know some also try using 99% isopropyl alcohol instead of ethanol, though I haven't tried this. One 80ml bottle will last you about a month at .5mg a day @ .24% concentration.

+

Preparation of gel

+

Gel preparation is quite simple, first you need to find out how much alcohol and water you need. You are trying to reach a concentration of 60/40 ethanol to water. You can easily find out how much water you need to reach an overall concentration of 60%(by volume). You can easily find online calculators for this, such as here: https://ezcalc.me/alcohol-dilution-calculator/. Assuming you want to make 100ml of gel, for example, and have 95%(190 proof) grain alcohol, you'll need ~63ml of 95% ethanol and 37ml of distilled water. From here on out I will assume you want 100ml of gel and have 95% ethanol.

+

 

+

Recipe

+

63ml ethanol
37ml distilled water
1g Carbomer 980
1.35g Triethanolamine
Estradiol to your desired concentration, I usually do .24%(by weight of the entire solution, accounting for the density of 95% ethanol at ~.8g/ml), which comes to ~215mg.

+

 

+

Procedure

+
    +
  1. Pour the ethanol into a mixing container, such as a beaker or jar.
  2. +
  3. Weigh your estradiol on a weighing paper, weighing boat, or a piece of tinfoil with your weighing spatulas, or another instrument.
  4. +
  5. Dissolve your estradiol into your ethanol and stir with a stirring instrument or coffee frother. Your solution should be clear, without any undissolved material.
  6. +
  7. Add water and stir.
  8. +
  9. Add Carbomer 980, and mix with coffee frother. This can take a long time to dissolve completely. I usually stir it with the coffee frother until most of it dissolves, then I let the solution sit while covered for 20 minutes. Then, I come back and stir it again until there are no clumps or undissolved powder.
  10. +
  11. Remove plunger from 100ml syringe. Twist on luer lock cap.
  12. +
  13. Transfer gel solution into your 100ml syringe, from the plunger side.
  14. +
  15. Add triethanolamine to your solution, stirring with your coffee frother. The solution will now go from liquid to a thicker gel, much like hand sanitizer. Stir extremely thoroughly and try to distribute the triethanolamine throughout the entire solution.
  16. +
  17. Insert plunger into back of syringe and remove the luer lock cap.
  18. +
  19. Use syringe to dispense gel into your airless pump of choice. You may want to stop a few times to let the gel settle to avoid huge air bubbles. You can tap the bottom of the airless pump against a hard surface to make the gel settle.
  20. +
+

 

+

Potential improvements and challenges

+

The hardest part of this procedure is working with the gel after triethanolamine has been added, as it almost immediately becomes very thick, clumpy, sticky, etc. You do not want to add triethanolamine to the gel before it is either in its final container, or in a syringe. If you add triethanolamine in the mixing container, it will be extremely difficult to transfer. If you get airless pumps of this style: https://www.aliexpress.com/item/2251832632413742.html you may be able to add the triethanolamine to the solution after it's already in the pump, however the mouth needs to be wide enough to fit your coffee frother. You need to be able to thoroughly mix the triethanolamine so that it can neutralize the pH of the carbomer 980. I haven't tried these bottles, but I have some other candidates on order and will update if I find a better bottle.

One possible area of improvement is adding a penetration enhancer, such as oleic acid, d-limonene, or isopropyl myristate. I personally experimented with 2% isopropyl myristate but found it incredibly irritating to my skin, and made the gel burn really badly. It also fell out of solution in my pump bottle. Personally, I just apply the gel scrotally, which results in extremely high absorption, so I feel no need to use penetration enhancers.

+

 

+

Usage/my results

+

With the bottles I recommend, each pump will dispense about 225mg of gel, or .5mg per pump. I used 4 pumps a day at first, putting 1 pump on my scrotum, and 1 on my thigh, morning and night, and after a month of this, I had the following blood test results:
Testosterone: 29 ng/dL
Estradiol: 326 pg/mL

I am currently lowering my dose to 2 pumps a day, on the scrotum only, to see if 1mg scrotally is enough for monotherapy. I will report back once I have blood test results. Although conventional wisdom with transdermal delivery says that transdermal gels have a depot effect, scrotal application has not been studied much and it could be the case that absorption is much quicker, so to be safe I apply twice a day rather than using 2 pumps once a day, and I also get my blood tests done at trough (before I do my morning dose).

This is a promising alternative to injections, and because it's alcohol based, the risk of contamination is low, even without a clean room or heat sterilization. This is also a great alternative for those who are needle-phobic or are for some reason not wanting to do injections.

If I can answer any questions, please feel free to reach out to me at owl@owl.haus or on discord: allie castro#1234

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/30843/171431.html b/groups.io/g/MTFHRT/wiki/30843/171431.html new file mode 100644 index 00000000..5d2292e9 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/30843/171431.html @@ -0,0 +1,1404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

DIY Estrogel Guide

+

This guide will instruct you on the materials and tools needed for home DIY basic estrogel compounding. There are easier methods out there, such as mixing estradiol into pre-made hand sanitizers, but this is for those who would prefer to compound their own gels, or manufacture at a scale where buying hand sanitizer is cost prohibitive. There are also some concerns about hand sanitizer formulations containing denaturing agents or other additives that might be bad for transdermal drug delivery. If you are interested in more experimental gel formulations or ones based on hand sanitizer, you can check out reddit.com/r/estrogel/wiki, which is where I got most of this information.

With this guide, you can produce supersaturated estrogels that are suitable for high-dose estradiol monotherapy. This is a great alternative to injections for the needle-shy or paranoid.

This recipe is based off of a patent that includes a generic estrogel recipe, available here: https://patents.google.com/patent/US20070154533A1/en - page 39 of the PDF has the recipe. This recipe has been adjusted for higher concentrations and higher absorption, using 60% ethanol, which is known to have the best absorption for estradiol. (https://sci-hub.se/https://doi.org/10.1016/j.addr.2012.09.032)

+

 

+

Sourcing Estradiol

+

The sources for estradiol are much the same as DIY injections, so I won't go into detail here. Look on made-in-china.com and search for 17b-estradiol, or more specifically, CAS number 50-28-2. For a single person, assuming they are doing monotherapy at 1-2mg a day, a typical yearly consumption is half a gram. This means 50 grams is enough to last you 100 years. I got 100 grams for $200 shipped from Hubei Vanz. You want 17 beta estradiol, not estradiol valerate, cypionate, enanthate, etc. 

+


Other ingredients

+

Other ingredients, including the quantity and price I got them before, are listed below.

+
    +
  • Carbomer/Carbopol 980 x 120g - $25 - amazon, ebay, cosmetic supply, aliexpress
  • +
  • Triethanolamine x 250ml - $20 - amazon, ebay, cosmetic supply
  • +
  • Distilled Water - $2-3 from your local grocery store
  • +
  • 95% (190 proof) grain alcohol, such as everclear - 750 ml - $20 - liquor store (any alcohol over 60%/120 proof is okay)
  • +
+

Tools

+
    +
  • Coffee frother wand - $5-10 on ebay, aliexpress, amazon. The longer and narrower the better.
  • +
  • Airless pump dispenser bottles - I have used this style(https://m.media-amazon.com/images/I/51D0UnNSu+L._SL1500_.jpg) in the past because one pump = 225mg which is roughly equivalent to .5mg of estradiol (at .24% concentration). This works out well for me because it means two pumps a day is enough for monotherapy. It also means 1 80 ml bottle (80 ml is just under the 3 oz limit on airplanes) is enough to last me roughly a month. These might not be the easiest pumps to work with though, but more on that later.
  • +
  • 100ml syringes with cap (like these https://www.amazon.com/100ml-Syringe-s-Caps-Industrial-Scientific/dp/B086H7TC1T) - also might not be necessary, more on that later
  • +
  • milligram scale such as the gemini-20 - $20-30
  • +
  • mixing container of some kind, such as a mason jar, glass cup, beaker, etc.
  • +
  • optional - metal stirrers and weighing spatulas such as these: https://www.amazon.com/gp/product/B07HHWCNB9/ - $10

  • +
+

Total: I spent about $350 to get started, but you can get everything much cheaper if you are willing to shop around and buy small quantities. The amount of carbomer, estradiol, triethanolamine, etc. per bottle is very little, so even small amounts will last you a long time. If you spent what I did, raw materials alone (not counting tools) and the pump bottle is about $5-10 per bottle. The most expensive components for me are ethanol and airless pumps. Buying airless pumps in bulk from alibaba or made-in-china sellers can get prices down lower, I know some also try using 99% isopropyl alcohol instead of ethanol, though I haven't tried this. One 80ml bottle will last you about a month at .5mg a day @ .24% concentration.

+

Preparation of gel

+

Gel preparation is quite simple, first you need to find out how much alcohol and water you need. You are trying to reach a concentration of 60/40 ethanol to water. You can easily find out how much water you need to reach an overall concentration of 60%(by volume). You can easily find online calculators for this, such as here: https://ezcalc.me/alcohol-dilution-calculator/. Assuming you want to make 100ml of gel, for example, and have 95%(190 proof) grain alcohol, you'll need ~63ml of 95% ethanol and 37ml of distilled water. From here on out I will assume you want 100ml of gel and have 95% ethanol.

+

 

+

Recipe

+

63ml ethanol
37ml distilled water
1g Carbomer 980
1.35g Triethanolamine
Estradiol to your desired concentration, I usually do .24%(by weight of the entire solution, accounting for the density of 95% ethanol at ~.8g/ml), which comes to ~215mg.

+

 

+

Procedure

+
    +
  1. Pour the ethanol into a mixing container, such as a beaker or jar.
  2. +
  3. Weigh your estradiol on a weighing paper, weighing boat, or a piece of tinfoil with your weighing spatulas, or another instrument.
  4. +
  5. Dissolve your estradiol into your ethanol and stir with a stirring instrument or coffee frother. Your solution should be clear, without any undissolved material.
  6. +
  7. Add water and stir.
  8. +
  9. Add Carbomer 980, and mix with coffee frother. This can take a long time to dissolve completely. I usually stir it with the coffee frother until most of it dissolves, then I let the solution sit while covered for 20 minutes. Then, I come back and stir it again until there are no clumps or undissolved powder.
  10. +
  11. Remove plunger from 100ml syringe. Twist on luer lock cap.
  12. +
  13. Transfer gel solution into your 100ml syringe, from the plunger side.
  14. +
  15. Add triethanolamine to your solution, stirring with your coffee frother. The solution will now go from liquid to a thicker gel, much like hand sanitizer. Stir extremely thoroughly and try to distribute the triethanolamine throughout the entire solution.
  16. +
  17. Insert plunger into back of syringe and remove the luer lock cap.
  18. +
  19. Use syringe to dispense gel into your airless pump of choice. You may want to stop a few times to let the gel settle to avoid huge air bubbles. You can tap the bottom of the airless pump against a hard surface to make the gel settle.
  20. +
+

 

+

Potential improvements and challenges

+

The hardest part of this procedure is working with the gel after triethanolamine has been added, as it almost immediately becomes very thick, clumpy, sticky, etc. You do not want to add triethanolamine to the gel before it is either in its final container, or in a syringe. If you add triethanolamine in the mixing container, it will be extremely difficult to transfer. If you get airless pumps of this style: https://www.aliexpress.com/item/2251832632413742.html you may be able to add the triethanolamine to the solution after it's already in the pump, however the mouth needs to be wide enough to fit your coffee frother. You need to be able to thoroughly mix the triethanolamine so that it can neutralize the pH of the carbomer 980. I haven't tried these bottles, but I have some other candidates on order and will update if I find a better bottle.

One possible area of improvement is adding a penetration enhancer, such as oleic acid, d-limonene, or isopropyl myristate. I personally experimented with 2% isopropyl myristate but found it incredibly irritating to my skin, and made the gel burn really badly. It also fell out of solution in my pump bottle. Personally, I just apply the gel scrotally, which results in extremely high absorption, so I feel no need to use penetration enhancers.

+

 

+

Usage/my results

+

With the bottles I recommend, each pump will dispense about 225mg of gel, or .5mg per pump. I used 4 pumps a day at first, putting 1 pump on my scrotum, and 1 on my thigh, morning and night, and after a month of this, I had the following blood test results:
Testosterone: 29 ng/dL
Estradiol: 326 pg/mL

I am currently lowering my dose to 2 pumps a day, on the scrotum only, to see if 1mg scrotally is enough for monotherapy. I will report back once I have blood test results. Although conventional wisdom with transdermal delivery says that transdermal gels have a depot effect, scrotal application has not been studied much and it could be the case that absorption is much quicker, so to be safe I apply twice a day rather than using 2 pumps once a day, and I also get my blood tests done at trough (before I do my morning dose).

This is a promising alternative to injections, and because it's alcohol based, the risk of contamination is low, even without a clean room or heat sterilization. This is also a great alternative for those who are needle-phobic or are for some reason not wanting to do injections.

If I can answer any questions, please feel free to reach out to me at owl@owl.haus or on discord: allie castro#1234

+

Discussion: https://groups.io/g/MTFHRT/topic/wiki_article_about_estrogel/93220481

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/30843/171432.html b/groups.io/g/MTFHRT/wiki/30843/171432.html new file mode 100644 index 00000000..d0e9750e --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/30843/171432.html @@ -0,0 +1,1404 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

DIY Estrogel Guide

+

This guide will instruct you on the materials and tools needed for home DIY basic estrogel compounding. There are easier methods out there, such as mixing estradiol into pre-made hand sanitizers, but this is for those who would prefer to compound their own gels, or manufacture at a scale where buying hand sanitizer is cost prohibitive. There are also some concerns about hand sanitizer formulations containing denaturing agents or other additives that might be bad for transdermal drug delivery. If you are interested in more experimental gel formulations or ones based on hand sanitizer, you can check out reddit.com/r/estrogel/wiki, which is where I got most of this information.

With this guide, you can produce supersaturated estrogels that are suitable for high-dose estradiol monotherapy. This is a great alternative to injections for the needle-shy or paranoid.

This recipe is based off of a patent that includes a generic estrogel recipe, available here: https://patents.google.com/patent/US20070154533A1/en - page 39 of the PDF has the recipe. This recipe has been adjusted for higher concentrations and higher absorption, using 60% ethanol, which is known to have the best absorption for estradiol. (https://sci-hub.se/https://doi.org/10.1016/j.addr.2012.09.032)

+

 

+

Sourcing Estradiol

+

The sources for estradiol are much the same as DIY injections, so I won't go into detail here. Look on made-in-china.com and search for 17b-estradiol, or more specifically, CAS number 50-28-2. For a single person, assuming they are doing monotherapy at 1-2mg a day, a typical yearly consumption is half a gram. This means 50 grams is enough to last you 100 years. I got 100 grams for $200 shipped from Hubei Vanz. You want 17 beta estradiol, not estradiol valerate, cypionate, enanthate, etc. 

+


Other ingredients

+

Other ingredients, including the quantity and price I got them before, are listed below.

+
    +
  • Carbomer/Carbopol 980 x 120g - $25 - amazon, ebay, cosmetic supply, aliexpress
  • +
  • Triethanolamine x 250ml - $20 - amazon, ebay, cosmetic supply
  • +
  • Distilled Water - $2-3 from your local grocery store
  • +
  • 95% (190 proof) grain alcohol, such as everclear - 750 ml - $20 - liquor store (any alcohol over 60%/120 proof is okay)
  • +
+

Tools

+
    +
  • Coffee frother wand - $5-10 on ebay, aliexpress, amazon. The longer and narrower the better.
  • +
  • Airless pump dispenser bottles - I have used this style(https://m.media-amazon.com/images/I/51D0UnNSu+L._SL1500_.jpg) in the past because one pump = 225mg which is roughly equivalent to .5mg of estradiol (at .24% concentration). This works out well for me because it means two pumps a day is enough for monotherapy. It also means 1 80 ml bottle (80 ml is just under the 3 oz limit on airplanes) is enough to last me roughly a month. These might not be the easiest pumps to work with though, but more on that later.
  • +
  • 100ml syringes with cap (like these https://www.amazon.com/100ml-Syringe-s-Caps-Industrial-Scientific/dp/B086H7TC1T) - also might not be necessary, more on that later
  • +
  • milligram scale such as the gemini-20 - $20-30
  • +
  • mixing container of some kind, such as a mason jar, glass cup, beaker, etc.
  • +
  • optional - metal stirrers and weighing spatulas such as these: https://www.amazon.com/gp/product/B07HHWCNB9/ - $10

  • +
+

Total: I spent about $350 to get started, but you can get everything much cheaper if you are willing to shop around and buy small quantities. The amount of carbomer, estradiol, triethanolamine, etc. per bottle is very little, so even small amounts will last you a long time. If you spent what I did, raw materials alone (not counting tools) and the pump bottle is about $5-10 per bottle. The most expensive components for me are ethanol and airless pumps. Buying airless pumps in bulk from alibaba or made-in-china sellers can get prices down lower, I know some also try using 99% isopropyl alcohol instead of ethanol, though I haven't tried this. One 80ml bottle will last you about a month at .5mg a day @ .24% concentration.

+

Preparation of gel

+

Gel preparation is quite simple, first you need to find out how much alcohol and water you need. You are trying to reach a concentration of 60/40 ethanol to water. You can easily find out how much water you need to reach an overall concentration of 60%(by volume). You can easily find online calculators for this, such as here: https://ezcalc.me/alcohol-dilution-calculator/. Assuming you want to make 100ml of gel, for example, and have 95%(190 proof) grain alcohol, you'll need ~63ml of 95% ethanol and 37ml of distilled water. From here on out I will assume you want 100ml of gel and have 95% ethanol.

+

 

+

Recipe

+

63ml ethanol
37ml distilled water
1g Carbomer 980
1.35g Triethanolamine
Estradiol to your desired concentration, I usually do .24%(by weight of the entire solution, accounting for the density of 95% ethanol at ~.8g/ml), which comes to ~215mg.

+

 

+

Procedure

+
    +
  1. Pour the ethanol into a mixing container, such as a beaker or jar.
  2. +
  3. Weigh your estradiol on a weighing paper, weighing boat, or a piece of tinfoil with your weighing spatulas, or another instrument.
  4. +
  5. Dissolve your estradiol into your ethanol and stir with a stirring instrument or coffee frother. Your solution should be clear, without any undissolved material.
  6. +
  7. Add water and stir.
  8. +
  9. Add Carbomer 980, and mix with coffee frother. This can take a long time to dissolve completely. I usually stir it with the coffee frother until most of it dissolves, then I let the solution sit while covered for 20 minutes. Then, I come back and stir it again until there are no clumps or undissolved powder.
  10. +
  11. Remove plunger from 100ml syringe. Twist on luer lock cap.
  12. +
  13. Transfer gel solution into your 100ml syringe, from the plunger side.
  14. +
  15. Add triethanolamine to your solution, stirring with your coffee frother. The solution will now go from liquid to a thicker gel, much like hand sanitizer. Stir extremely thoroughly and try to distribute the triethanolamine throughout the entire solution.
  16. +
  17. Insert plunger into back of syringe and remove the luer lock cap.
  18. +
  19. Use syringe to dispense gel into your airless pump of choice. You may want to stop a few times to let the gel settle to avoid huge air bubbles. You can tap the bottom of the airless pump against a hard surface to make the gel settle.
  20. +
+

 

+

Potential improvements and challenges

+

The hardest part of this procedure is working with the gel after triethanolamine has been added, as it almost immediately becomes very thick, clumpy, sticky, etc. You do not want to add triethanolamine to the gel before it is either in its final container, or in a syringe. If you add triethanolamine in the mixing container, it will be extremely difficult to transfer. If you get airless pumps of this style: https://www.aliexpress.com/item/2251832632413742.html you may be able to add the triethanolamine to the solution after it's already in the pump, however the mouth needs to be wide enough to fit your coffee frother. You need to be able to thoroughly mix the triethanolamine so that it can neutralize the pH of the carbomer 980. I haven't tried these bottles, but I have some other candidates on order and will update if I find a better bottle.

One possible area of improvement is adding a penetration enhancer, such as oleic acid, d-limonene, or isopropyl myristate. I personally experimented with 2% isopropyl myristate but found it incredibly irritating to my skin, and made the gel burn really badly. It also fell out of solution in my pump bottle. Personally, I just apply the gel scrotally, which results in extremely high absorption, so I feel no need to use penetration enhancers.

+

 

+

Usage/my results

+

With the bottles I recommend, each pump will dispense about 225mg of gel, or .5mg per pump. I used 4 pumps a day at first, putting 1 pump on my scrotum, and 1 on my thigh, morning and night, and after a month of this, I had the following blood test results:
Testosterone: 29 ng/dL
Estradiol: 326 pg/mL

I am currently lowering my dose to 2 pumps a day, on the scrotum only, to see if 1mg scrotally is enough for monotherapy. I will report back once I have blood test results. Although conventional wisdom with transdermal delivery says that transdermal gels have a depot effect, scrotal application has not been studied much and it could be the case that absorption is much quicker, so to be safe I apply twice a day rather than using 2 pumps once a day, and I also get my blood tests done at trough (before I do my morning dose).

This is a promising alternative to injections, and because it's alcohol based, the risk of contamination is low, even without a clean room or heat sterilization. This is also a great alternative for those who are needle-phobic or are for some reason not wanting to do injections.

If I can answer any questions, please feel free to reach out to me at owl@owl.haus or on discord: allie castro#1234

+

Discussion: https://groups.io/g/MTFHRT/topic/wiki_article_about_estrogel/93220481

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/30843/history.html b/groups.io/g/MTFHRT/wiki/30843/history.html index ddc91ece..83c6dca7 100644 --- a/groups.io/g/MTFHRT/wiki/30843/history.html +++ b/groups.io/g/MTFHRT/wiki/30843/history.html @@ -6,7 +6,7 @@ - + @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774628.1713918440736062136"); + console.log("client_id:", "web.web09.236702.1714523380049246401"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774628.1713918440736062136" + client_id: "web.web09.236702.1714523380049246401" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { - + - - + + @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -589,7 +914,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="171432"> + <a href="171432.html"> @@ -623,7 +948,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="171431"> + <a href="171431.html"> @@ -655,7 +980,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="171365"> + <a href="171365.html"> @@ -687,7 +1012,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="171364"> + <a href="171364.html"> @@ -719,7 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="171363"> + <a href="171363.html"> Publishing v1 of the estrogel guide @@ -742,6 +1067,10 @@ function createAlert(msg, isError, autoClose, noClose) { </form> <script type="text/javascript"> +contentLoaded(false, function() { + + UpdateSidebar("wiki"); +}); function countChecked(id) { var checkedVal = 0; @@ -768,20 +1097,20 @@ function countChecked(id) { } </script> + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -791,9 +1120,7 @@ function countChecked(id) { </div> </div> - - @@ -822,48 +1149,43 @@ function countChecked(id) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -878,13 +1200,17 @@ function countChecked(id) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -906,7 +1232,7 @@ function countChecked(id) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -927,138 +1253,144 @@ function countChecked(id) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1080,6 +1412,21 @@ function countChecked(id) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30846.html b/groups.io/g/MTFHRT/wiki/30846.html index 440768f4..645644fe 100644 --- a/groups.io/g/MTFHRT/wiki/30846.html +++ b/groups.io/g/MTFHRT/wiki/30846.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774005.1713918438187784055"); + console.log("client_id:", "web.web09.236585.1714523377608880674"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774005.1713918438187784055" + client_id: "web.web09.236585.1714523377608880674" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Home</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Home</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,51 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated30846"> - $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false - )); -</script> - · - <a href="30846/history.html"> - 5 revisions - </a> -    - <a href="30846.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p><a href="29602.html" rel="nofollow">Injections</a></p> -<p><a href="30843.html" rel="nofollow">Gel</a></p> -<p><a title="How to measure melting point of most organic powders using typical household items." href="32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> -<p>Literature and discussions on:</p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">hGH, igf-1 and effects on hrt</a></p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/79606271" rel="nofollow">Hrt and brain</a></p> -<p> </p> -<p> </p> -<p> </p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -684,25 +970,74 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated30846"> + $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false + )); +</script> + · + <a href="30846/history.html"> + 5 revisions + </a> +    + <a href="30846.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p><a href="29602.html" rel="nofollow">Injections</a></p> +<p><a href="30843.html" rel="nofollow">Gel</a></p> +<p><a title="How to measure melting point of most organic powders using typical household items." href="32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> +<p>Literature and discussions on:</p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">hGH, igf-1 and effects on hrt</a></p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/79606271" rel="nofollow">Hrt and brain</a></p> +<p> </p> +<p> </p> +<p> </p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -712,9 +1047,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -743,48 +1076,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -799,13 +1127,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -827,7 +1159,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -848,138 +1180,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1001,6 +1339,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30846/171373.html b/groups.io/g/MTFHRT/wiki/30846/171373.html index 8ebd65ca..d34aa991 100644 --- a/groups.io/g/MTFHRT/wiki/30846/171373.html +++ b/groups.io/g/MTFHRT/wiki/30846/171373.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774118.1713918440301729467"); + console.log("client_id:", "web.web08.237148.1714523381058446840"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774118.1713918440301729467" + client_id: "web.web08.237148.1714523381058446840" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Home</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Home</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,44 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated30846"> - $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false - )); -</script> - · - <a href="history.html"> - 5 revisions - </a> -    - <a href="../30846.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p><a href="../29602.html" rel="nofollow">Injections</a></p> -<p><a href="../30843.html" rel="nofollow">Gel</a></p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -677,25 +970,67 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated30846"> + $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false + )); +</script> + · + <a href="history.html"> + 5 revisions + </a> +    + <a href="../30846.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p><a href="../29602.html" rel="nofollow">Injections</a></p> +<p><a href="../30843.html" rel="nofollow">Gel</a></p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -705,9 +1040,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -736,48 +1069,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -792,13 +1120,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -820,7 +1152,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -841,138 +1173,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -994,6 +1332,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30846/175561.html b/groups.io/g/MTFHRT/wiki/30846/175561.html index e7eda42c..be04e259 100644 --- a/groups.io/g/MTFHRT/wiki/30846/175561.html +++ b/groups.io/g/MTFHRT/wiki/30846/175561.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774611.1713918440236052559"); + console.log("client_id:", "web.web09.236743.1714523380975210372"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774611.1713918440236052559" + client_id: "web.web09.236743.1714523380975210372" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Home</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Home</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,45 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated30846"> - $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false - )); -</script> - · - <a href="history.html"> - 5 revisions - </a> -    - <a href="../30846.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p><a href="../29602.html" rel="nofollow">Injections</a></p> -<p><a href="../30843.html" rel="nofollow">Gel</a></p> -<p><a title="How to measure melting point of most organic powders using typical household items." href="../32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -678,25 +970,68 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated30846"> + $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false + )); +</script> + · + <a href="history.html"> + 5 revisions + </a> +    + <a href="../30846.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p><a href="../29602.html" rel="nofollow">Injections</a></p> +<p><a href="../30843.html" rel="nofollow">Gel</a></p> +<p><a title="How to measure melting point of most organic powders using typical household items." href="../32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -706,9 +1041,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -737,48 +1070,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -793,13 +1121,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -821,7 +1153,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -842,138 +1174,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -995,6 +1333,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30846/175575.html b/groups.io/g/MTFHRT/wiki/30846/175575.html index c43386fb..71f70d6e 100644 --- a/groups.io/g/MTFHRT/wiki/30846/175575.html +++ b/groups.io/g/MTFHRT/wiki/30846/175575.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774107.1713918440167908054"); + console.log("client_id:", "web.web08.237142.1714523380888093416"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774107.1713918440167908054" + client_id: "web.web08.237142.1714523380888093416" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Home</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Home</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,50 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated30846"> - $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false - )); -</script> - · - <a href="history.html"> - 5 revisions - </a> -    - <a href="../30846.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p><a href="../29602.html" rel="nofollow">Injections</a></p> -<p><a href="../30843.html" rel="nofollow">Gel</a></p> -<p><a title="How to measure melting point of most organic powders using typical household items." href="../32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> -<p>Literature and discussions on:</p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">Hrt and brain</a></p> -<p> </p> -<p> </p> -<p> </p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -683,25 +970,73 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated30846"> + $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false + )); +</script> + · + <a href="history.html"> + 5 revisions + </a> +    + <a href="../30846.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p><a href="../29602.html" rel="nofollow">Injections</a></p> +<p><a href="../30843.html" rel="nofollow">Gel</a></p> +<p><a title="How to measure melting point of most organic powders using typical household items." href="../32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> +<p>Literature and discussions on:</p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">Hrt and brain</a></p> +<p> </p> +<p> </p> +<p> </p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -711,9 +1046,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -742,48 +1075,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -798,13 +1126,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -826,7 +1158,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -847,138 +1179,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1000,6 +1338,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30846/175576.html b/groups.io/g/MTFHRT/wiki/30846/175576.html index 0095ef0e..ae59436e 100644 --- a/groups.io/g/MTFHRT/wiki/30846/175576.html +++ b/groups.io/g/MTFHRT/wiki/30846/175576.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774595.1713918440101304545"); + console.log("client_id:", "web.web09.236734.1714523380805581536"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774595.1713918440101304545" + client_id: "web.web09.236734.1714523380805581536" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Home</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Home</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,51 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated30846"> - $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false - )); -</script> - · - <a href="history.html"> - 5 revisions - </a> -    - <a href="../30846.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p><a href="../29602.html" rel="nofollow">Injections</a></p> -<p><a href="../30843.html" rel="nofollow">Gel</a></p> -<p><a title="How to measure melting point of most organic powders using typical household items." href="../32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> -<p>Literature and discussions on:</p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">hGH, igf-1 and effects on hrt</a></p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/79606271#7645" rel="nofollow">Hrt and brain</a></p> -<p> </p> -<p> </p> -<p> </p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -684,25 +970,74 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated30846"> + $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false + )); +</script> + · + <a href="history.html"> + 5 revisions + </a> +    + <a href="../30846.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p><a href="../29602.html" rel="nofollow">Injections</a></p> +<p><a href="../30843.html" rel="nofollow">Gel</a></p> +<p><a title="How to measure melting point of most organic powders using typical household items." href="../32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> +<p>Literature and discussions on:</p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">hGH, igf-1 and effects on hrt</a></p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/79606271#7645" rel="nofollow">Hrt and brain</a></p> +<p> </p> +<p> </p> +<p> </p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -712,9 +1047,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -743,48 +1076,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -799,13 +1127,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -827,7 +1159,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -848,138 +1180,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1001,6 +1339,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30846/175577.html b/groups.io/g/MTFHRT/wiki/30846/175577.html index 21aed2e6..052f52cc 100644 --- a/groups.io/g/MTFHRT/wiki/30846/175577.html +++ b/groups.io/g/MTFHRT/wiki/30846/175577.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774095.1713918440033905718"); + console.log("client_id:", "web.web08.237133.1714523380716243082"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774095.1713918440033905718" + client_id: "web.web08.237133.1714523380716243082" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Home</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Home</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,51 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated30846"> - $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false - )); -</script> - · - <a href="history.html"> - 5 revisions - </a> -    - <a href="../30846.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p><a href="../29602.html" rel="nofollow">Injections</a></p> -<p><a href="../30843.html" rel="nofollow">Gel</a></p> -<p><a title="How to measure melting point of most organic powders using typical household items." href="../32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> -<p>Literature and discussions on:</p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">hGH, igf-1 and effects on hrt</a></p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/79606271" rel="nofollow">Hrt and brain</a></p> -<p> </p> -<p> </p> -<p> </p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -684,25 +970,74 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated30846"> + $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false + )); +</script> + · + <a href="history.html"> + 5 revisions + </a> +    + <a href="../30846.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p><a href="../29602.html" rel="nofollow">Injections</a></p> +<p><a href="../30843.html" rel="nofollow">Gel</a></p> +<p><a title="How to measure melting point of most organic powders using typical household items." href="../32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> +<p>Literature and discussions on:</p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">hGH, igf-1 and effects on hrt</a></p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/79606271" rel="nofollow">Hrt and brain</a></p> +<p> </p> +<p> </p> +<p> </p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -712,9 +1047,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -743,48 +1076,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -799,13 +1127,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -827,7 +1159,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -848,138 +1180,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1001,6 +1339,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/30846/history.html b/groups.io/g/MTFHRT/wiki/30846/history.html index 0ac2f95e..d08a95b9 100644 --- a/groups.io/g/MTFHRT/wiki/30846/history.html +++ b/groups.io/g/MTFHRT/wiki/30846/history.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774003.1713918438122765430"); + console.log("client_id:", "web.web08.237006.1714523377966153663"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774003.1713918438122765430" + client_id: "web.web08.237006.1714523377966153663" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -743,6 +1068,10 @@ function createAlert(msg, isError, autoClose, noClose) { </form> <script type="text/javascript"> +contentLoaded(false, function() { + + UpdateSidebar("wiki"); +}); function countChecked(id) { var checkedVal = 0; @@ -769,20 +1098,20 @@ function countChecked(id) { } </script> + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -792,9 +1121,7 @@ function countChecked(id) { </div> </div> - - @@ -823,48 +1150,43 @@ function countChecked(id) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -879,13 +1201,17 @@ function countChecked(id) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -907,7 +1233,7 @@ function countChecked(id) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -928,138 +1254,144 @@ function countChecked(id) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1081,6 +1413,21 @@ function countChecked(id) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/32288.html b/groups.io/g/MTFHRT/wiki/32288.html index 195cd3ef..f42170d7 100644 --- a/groups.io/g/MTFHRT/wiki/32288.html +++ b/groups.io/g/MTFHRT/wiki/32288.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774515.1713918438404139241"); + console.log("client_id:", "web.web09.236590.1714523377689752164"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774515.1713918438404139241" + client_id: "web.web09.236590.1714523377689752164" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> How to measure melting point of most organic powders using typical household items.</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> How to measure melting point of most organic powders using typical household items.</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,62 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated32288"> - $('#timedispupdated32288').replaceWith(DisplayShortTime(1666754939519775143, false - )); -</script> - · - <a href="32288/history.html"> - 1 revision - </a> -    - <a href="32288.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p>Tools</p> -<ul> -<li>Single-egg frying pan. You can use something bigger, but you'll need more oil.</li> -<li>Half a cup of cooking oil, more for larger pan.</li> -<li>Small metal cap, such as the cap of a beer bottle.</li> -<li>Digital meat/candy themometer. (example: Taylor's folding thermometer's range is -40°C to 230°C)</li> -</ul> -<p>Procedure</p> -<ol> -<li>Place oil in frying pan</li> -<li>Place cap like a little boat in the oil</li> -<li>Place tiny bit of powder on the boat</li> -<li>Suspend probe of thermometer into the oil, but not touching the sides</li> -<li>Double check it's not touching the sides, and is just in the oil</li> -<li>Heat slowly (low, low heat)</li> -<li>Note temp where it 'pauses' briefly while the substance turns to liquid</li> -</ol> -<p> </p> -<p><img src="https://i.imgur.com/LOWBMtc.png" class="myimg-responsive"/></p> -<p><br/>My test today, I was off by 0.2°C from expected value. Absolutely within tolerance. <br/><br/>The above setup can be had for around $10-20 US, if you don't have stuff laying around, and really is 'accurate enough'. </p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -695,25 +970,85 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated32288"> + $('#timedispupdated32288').replaceWith(DisplayShortTime(1666754939519775143, false + )); +</script> + · + <a href="32288/history.html"> + 1 revision + </a> +    + <a href="32288.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p>Tools</p> +<ul> +<li>Single-egg frying pan. You can use something bigger, but you'll need more oil.</li> +<li>Half a cup of cooking oil, more for larger pan.</li> +<li>Small metal cap, such as the cap of a beer bottle.</li> +<li>Digital meat/candy themometer. (example: Taylor's folding thermometer's range is -40°C to 230°C)</li> +</ul> +<p>Procedure</p> +<ol> +<li>Place oil in frying pan</li> +<li>Place cap like a little boat in the oil</li> +<li>Place tiny bit of powder on the boat</li> +<li>Suspend probe of thermometer into the oil, but not touching the sides</li> +<li>Double check it's not touching the sides, and is just in the oil</li> +<li>Heat slowly (low, low heat)</li> +<li>Note temp where it 'pauses' briefly while the substance turns to liquid</li> +</ol> +<p> </p> +<p><img src="https://i.imgur.com/LOWBMtc.png" class="myimg-responsive"/></p> +<p><br/>My test today, I was off by 0.2°C from expected value. Absolutely within tolerance. <br/><br/>The above setup can be had for around $10-20 US, if you don't have stuff laying around, and really is 'accurate enough'. </p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -723,9 +1058,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -754,48 +1087,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -810,13 +1138,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -838,7 +1170,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -859,138 +1191,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1012,6 +1350,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/32288/175560.html b/groups.io/g/MTFHRT/wiki/32288/175560.html new file mode 100644 index 00000000..07f26bcc --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/32288/175560.html @@ -0,0 +1,1375 @@ + + + <!DOCTYPE html> + <html lang="en-US"> + <head> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <meta name="pinterest" content="nopin" /> + <meta name="pinterest" content="nohover" /> + + <meta name="3778517eb4810dfb5d143ed8f1b359b3b5a82923" content="0f56257c3db4a222e91b11bc6871c4df2e263b28" /> + <link rel="apple-touch-icon" sizes="57x57" href="https://groups.io/img/org.1/favicons/apple-icon-57x57.png"> + <link rel="apple-touch-icon" sizes="60x60" href="https://groups.io/img/org.1/favicons/apple-icon-60x60.png"> + <link rel="apple-touch-icon" sizes="72x72" href="https://groups.io/img/org.1/favicons/apple-icon-72x72.png"> + <link rel="apple-touch-icon" sizes="76x76" href="https://groups.io/img/org.1/favicons/apple-icon-76x76.png"> + <link rel="apple-touch-icon" sizes="114x114" href="https://groups.io/img/org.1/favicons/apple-icon-114x114.png"> + <link rel="apple-touch-icon" sizes="120x120" href="https://groups.io/img/org.1/favicons/apple-icon-120x120.png"> + <link rel="apple-touch-icon" sizes="144x144" href="https://groups.io/img/org.1/favicons/apple-icon-144x144.png"> + <link rel="apple-touch-icon" sizes="152x152" href="https://groups.io/img/org.1/favicons/apple-icon-152x152.png"> + <link rel="apple-touch-icon" sizes="180x180" href="https://groups.io/img/org.1/favicons/apple-icon-180x180.png"> + <link rel="icon" type="image/png" sizes="192x192" href="../../../../img/org.1/favicons/android-icon-192x192.png"> + <link rel="icon" type="image/png" sizes="32x32" href="../../../../img/org.1/favicons/favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="96x96" href="../../../../img/org.1/favicons/favicon-96x96.png"> + <link rel="icon" type="image/png" sizes="16x16" href="../../../../img/org.1/favicons/favicon-16x16.png"> + <link rel="manifest" href="../../../../img/org.1/favicons/manifest.json"> + <meta name="msapplication-TileColor" content="#ffffff"> + <meta name="msapplication-TileImage" content="/ms-icon-144x144.png"> + + + + +<script> +/* stubs */ +const hapticsImpactHeavy = async () => { +}; +const hapticsImpactMedium = async () => { +}; +const hapticsImpactLight = async () => { +}; +const hapticsVibrate = async () => { +}; +const hapticsSelectionStart = async () => { +}; +const hapticsSelectionChanged = async () => { +}; +const hapticsSelectionEnd = async () => { +}; +</script> + + +<script> + + function setPullToRefresh() {} + + function gotoURL(inurl) { + window.location.href = inurl; + return; + } + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); + if (isHTMX == true) { + document.body.addEventListener('htmx:afterSettle', f, {once: true}); + } else { + if (document.readyState !== 'loading') { + console.log('document is already ready, just execute code here'); + f(); + } else { + console.log('document was not ready, place code here'); + document.addEventListener('DOMContentLoaded', f, {once: true}); + } + } + } + + // stub + function logError(data, url, linenumber) { + console.log(data) + return; + } + var pushSubToken; + var ignoreErrors = false; + var lastError = ""; + + window.onerror = function(errorMessage, errorUrl, errorLine, errorColumn, errorObj) { + let column; + let stack; + if (console && console.log) { + console.log("msg:", errorMessage); + console.log("url:", errorUrl); + console.log("line:", errorLine); + if (errorColumn !== undefined && errorObj != null) { + console.log("column:", errorColumn); + column = errorColumn; + } + if (errorObj !== undefined && errorObj != null) { + console.log("stack:", errorObj.stack); + stack = errorObj.stack; + } + console.log("client_id:", "web.web08.237168.1714523381578941836"); + console.log("last_error:", lastError); + console.log("stack:", stack); + } + if (errorUrl == "" || errorUrl === null) { + errorUrl = window.location.href; + } + if (errorMessage.includes("SecurityError:") == true) { + ignoreErrors = true; + } + if (ignoreErrors == true) { + console.log("cookies, disabled, ignoring"); + lastError = errorMessage; + return; + } + jQuery.ajax({ + type: 'POST', + url: '/jsclienterror', + data: { + msg: errorMessage, + url: errorUrl, + line: errorLine, + column: column, + stack: stack, + last_error: lastError, + client_id: "web.web08.237168.1714523381578941836" + }, + success: function() { + if (console && console.log) { + console.log('JS error report successful.'); + } + lastError = errorMessage; + }, + error: function() { + if (console && console.error) { + console.error('JS error report submission failed!'); + } + lastError = errorMessage; + } + }); + return true; + } + +</script> + + + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> + <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> + <script src="../../../../js/run_prettify.js"></script> + <title> + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 1 revision + +    + + + +
+ +
+
+ +
+
+ + +

Tools

+
    +
  • Single-egg frying pan. You can use something bigger, but you'll need more oil.
  • +
  • Half a cup of cooking oil, more for larger pan.
  • +
  • Small metal cap, such as the cap of a beer bottle.
  • +
  • Digital meat/candy themometer. (example: Taylor's folding thermometer's range is -40°C to 230°C)
  • +
+

Procedure

+
    +
  1. Place oil in frying pan
  2. +
  3. Place cap like a little boat in the oil
  4. +
  5. Place tiny bit of powder on the boat
  6. +
  7. Suspend probe of thermometer into the oil, but not touching the sides
  8. +
  9. Double check it's not touching the sides, and is just in the oil
  10. +
  11. Heat slowly (low, low heat)
  12. +
  13. Note temp where it 'pauses' briefly while the substance turns to liquid
  14. +
+

 

+

+


My test today, I was off by 0.2°C from expected value. Absolutely within tolerance.

The above setup can be had for around $10-20 US, if you don't have stuff laying around, and really is 'accurate enough'.

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/32288/history.html b/groups.io/g/MTFHRT/wiki/32288/history.html index a5bdedd0..ce7d016a 100644 --- a/groups.io/g/MTFHRT/wiki/32288/history.html +++ b/groups.io/g/MTFHRT/wiki/32288/history.html @@ -6,7 +6,7 @@ - + @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774136.1713918440803701915"); + console.log("client_id:", "web.web08.237107.1714523380129608427"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774136.1713918440803701915" + client_id: "web.web08.237107.1714523380129608427" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { - + - - + + @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -587,7 +912,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="175560"> + <a href="175560.html"> @@ -613,9 +938,13 @@ function createAlert(msg, isError, autoClose, noClose) { </form> <script type="text/javascript"> +contentLoaded(false, function() { $("#compare").prop("disabled", true); + UpdateSidebar("wiki"); +}); + function countChecked(id) { var checkedVal = 0; var cbs = document.getElementsByTagName('input'); @@ -641,20 +970,20 @@ function countChecked(id) { } </script> + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -664,9 +993,7 @@ function countChecked(id) { </div> </div> - - @@ -695,48 +1022,43 @@ function countChecked(id) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -751,13 +1073,17 @@ function countChecked(id) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -779,7 +1105,7 @@ function countChecked(id) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -800,138 +1126,144 @@ function countChecked(id) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -953,6 +1285,21 @@ function countChecked(id) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/34293.html b/groups.io/g/MTFHRT/wiki/34293.html index 4568a63c..b183bf3c 100644 --- a/groups.io/g/MTFHRT/wiki/34293.html +++ b/groups.io/g/MTFHRT/wiki/34293.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web08.774516.1713918438474946972"); + console.log("client_id:", "web.web08.236996.1714523377772569675"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web08.774516.1713918438474946972" + client_id: "web.web08.236996.1714523377772569675" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> steam sterilization</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> steam sterilization</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,48 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated34293"> - $('#timedispupdated34293').replaceWith(DisplayShortTime(1710077412941562435, false - )); -</script> - · - <a href="34293/history.html"> - 5 revisions - </a> -    - <a href="34293.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p>An article on pharmaceutical engineering says: <span style="background-color: #ff99cc;">Direct steam contact with the surface of the object to be sterilized is required for the steam to transfer its stored energy to the object. Without direct steam contact to all surfaces, the item will not be sterilized. The amount of energy stored in steam is much higher than dry air or water at the same temperature. From the saturated steam table mentioned above, one can see that it takes 419 kJ/kg (180 Btu/lb) to heat water from 0°C to 100°C (32°F to 212°F). This is the enthalpy of water (hl). It takes an additional 2,257 kJ/kg (970 Btu/lb) to create steam at atmospheric pressure (100°C or 212°F). This additional energy stored in the steam is the enthalpy of vaporization (he), and is the key to steam sterilization. In order for the steam to transfer its stored energy, it must condense on the surface of the object being sterilized.</span></p> -<p>The energy that article talks about is thermal energy. If you pour dry powder into a vial, seal the stopper and heat the vial, the heat is conducted from the glass into the powder quite slowly because heat conduction in unmoving dry powder (with air between particles) is slow. After half hour heating, part of the powder remains relatively cold, unsterilized. The sterilization time begins when everything is heated enough - it's why the talk about "energy transfer".</p> -<p>Thermal energy can be transferred by condensation of steam (as explained in the quote above) or by <a href="https://en.wikipedia.org/wiki/Heat_transfer#Mechanisms" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">conduction, radiation or convection</span></a>. Conduction is indeed quite slow. Convection of dry air transfers thermal energy not enough fast. However, the author of that article talks about a "steam autoclave" implying that the water boiling in one part of the autoclave is not in direct contact with the items intended to be sterilized. If a vial is submerged in boiling water, convection in boiling water transfers thermal energy into the vial very, very much faster. If the vial contains a solution instead of a dry powder, the solution inside the vial also convects, the thermal energy is quickly transferred to every part of the solution, so if you submerge the vial in water boiling in a 15 PSI (or 100 kPa) pressure cooker then entire solution in the vial is quickly heated to 121°C.</p> -<p>I was asked "how quickly?". I did an experiment with viscous Castor oil (slow convection) and a digital thermometer with long thin sharp probe. I mixed 10 ml of solution with Castor oil and 2% benzyl alcohol in a vial, sealed and crimped the vial, pierced the rubber stopper with the probe (so that the thermo-sensitive end of the probe was at the center of the solution in the vial) and plunged most, but not all height of the vial into water boiling in a pot (so that the probe didn't touch the water). The numbers the thermometer indicated rose from 26°C to 95°C during 4.5 min. Then I cooled the probe in cold tap water to 16°C and plunged the probe directly into boiling water. The numbers rose to 95°C during 0.5 min (because the probe with metal coating has thermal inertia).</p> -<p>The <a href="https://www.amazon.com/EustomA-Autoclave-Temperature-Pressure-Equipment/dp/B09CPSFMXZ/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">XFS-260</span></a> autoclave I use is similar to a pressure cooker, but has two bowls. The inner bowl is made of thin stainless steel. I pour water into the outer bowl up to slightly above the bottom of the inner bowl, and pour water into the inner bowl too. So, vials are submerged in water boiling at 129°C (under pressure 24 PSI). Thermal energy is quickly transferred by convection into every part of the solution inside the vials.</p> -<p>Officially 121°C for <span style="text-decoration: underline;"><a href="https://www.pharmacy180.com/article/sterilization-considerations--656/" target="_blank" rel="nofollow noopener">8 minutes</a></span> is enough. Add 4 min for heat transfer into the vial. 30 min is overkill I added before the experiment to be sure that the temperature 121°C is reached inside the vial too. For 100°C the <span style="text-decoration: underline;"><a href="https://web.archive.org/web/20070203042243/http://www.cip.ukcentre.com/fo.htm" target="_blank" rel="nofollow noopener">theory</a></span> says longer time is required, but the heat-resistant pathogenic bacteria (tetanus, botulism) are anaerobic, oxygen containing in the air inside the vial is a poison for them, and the waterless solution is not nutritious for them (unlike canned meat).</p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -681,25 +970,71 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated34293"> + $('#timedispupdated34293').replaceWith(DisplayShortTime(1710077412941562435, false + )); +</script> + · + <a href="34293/history.html"> + 5 revisions + </a> +    + <a href="34293.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p>An article on pharmaceutical engineering says: <span style="background-color: #ff99cc;">Direct steam contact with the surface of the object to be sterilized is required for the steam to transfer its stored energy to the object. Without direct steam contact to all surfaces, the item will not be sterilized. The amount of energy stored in steam is much higher than dry air or water at the same temperature. From the saturated steam table mentioned above, one can see that it takes 419 kJ/kg (180 Btu/lb) to heat water from 0°C to 100°C (32°F to 212°F). This is the enthalpy of water (hl). It takes an additional 2,257 kJ/kg (970 Btu/lb) to create steam at atmospheric pressure (100°C or 212°F). This additional energy stored in the steam is the enthalpy of vaporization (he), and is the key to steam sterilization. In order for the steam to transfer its stored energy, it must condense on the surface of the object being sterilized.</span></p> +<p>The energy that article talks about is thermal energy. If you pour dry powder into a vial, seal the stopper and heat the vial, the heat is conducted from the glass into the powder quite slowly because heat conduction in unmoving dry powder (with air between particles) is slow. After half hour heating, part of the powder remains relatively cold, unsterilized. The sterilization time begins when everything is heated enough - it's why the talk about "energy transfer".</p> +<p>Thermal energy can be transferred by condensation of steam (as explained in the quote above) or by <a href="https://en.wikipedia.org/wiki/Heat_transfer#Mechanisms" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">conduction, radiation or convection</span></a>. Conduction is indeed quite slow. Convection of dry air transfers thermal energy not enough fast. However, the author of that article talks about a "steam autoclave" implying that the water boiling in one part of the autoclave is not in direct contact with the items intended to be sterilized. If a vial is submerged in boiling water, convection in boiling water transfers thermal energy into the vial very, very much faster. If the vial contains a solution instead of a dry powder, the solution inside the vial also convects, the thermal energy is quickly transferred to every part of the solution, so if you submerge the vial in water boiling in a 15 PSI (or 100 kPa) pressure cooker then entire solution in the vial is quickly heated to 121°C.</p> +<p>I was asked "how quickly?". I did an experiment with viscous Castor oil (slow convection) and a digital thermometer with long thin sharp probe. I mixed 10 ml of solution with Castor oil and 2% benzyl alcohol in a vial, sealed and crimped the vial, pierced the rubber stopper with the probe (so that the thermo-sensitive end of the probe was at the center of the solution in the vial) and plunged most, but not all height of the vial into water boiling in a pot (so that the probe didn't touch the water). The numbers the thermometer indicated rose from 26°C to 95°C during 4.5 min. Then I cooled the probe in cold tap water to 16°C and plunged the probe directly into boiling water. The numbers rose to 95°C during 0.5 min (because the probe with metal coating has thermal inertia).</p> +<p>The <a href="https://www.amazon.com/EustomA-Autoclave-Temperature-Pressure-Equipment/dp/B09CPSFMXZ/" target="_blank" rel="nofollow noopener"><span style="text-decoration: underline;">XFS-260</span></a> autoclave I use is similar to a pressure cooker, but has two bowls. The inner bowl is made of thin stainless steel. I pour water into the outer bowl up to slightly above the bottom of the inner bowl, and pour water into the inner bowl too. So, vials are submerged in water boiling at 129°C (under pressure 24 PSI). Thermal energy is quickly transferred by convection into every part of the solution inside the vials.</p> +<p>Officially 121°C for <span style="text-decoration: underline;"><a href="https://www.pharmacy180.com/article/sterilization-considerations--656/" target="_blank" rel="nofollow noopener">8 minutes</a></span> is enough. Add 4 min for heat transfer into the vial. 30 min is overkill I added before the experiment to be sure that the temperature 121°C is reached inside the vial too. For 100°C the <span style="text-decoration: underline;"><a href="https://web.archive.org/web/20070203042243/http://www.cip.ukcentre.com/fo.htm" target="_blank" rel="nofollow noopener">theory</a></span> says longer time is required, but the heat-resistant pathogenic bacteria (tetanus, botulism) are anaerobic, oxygen containing in the air inside the vial is a poison for them, and the waterless solution is not nutritious for them (unlike canned meat).</p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -709,9 +1044,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -740,48 +1073,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -796,13 +1124,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -824,7 +1156,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -845,138 +1177,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -998,6 +1336,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/34293/189320.html b/groups.io/g/MTFHRT/wiki/34293/189320.html new file mode 100644 index 00000000..52400c55 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/34293/189320.html @@ -0,0 +1,1360 @@ + + + <!DOCTYPE html> + <html lang="en-US"> + <head> + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <meta name="pinterest" content="nopin" /> + <meta name="pinterest" content="nohover" /> + + <meta name="3778517eb4810dfb5d143ed8f1b359b3b5a82923" content="0f56257c3db4a222e91b11bc6871c4df2e263b28" /> + <link rel="apple-touch-icon" sizes="57x57" href="https://groups.io/img/org.1/favicons/apple-icon-57x57.png"> + <link rel="apple-touch-icon" sizes="60x60" href="https://groups.io/img/org.1/favicons/apple-icon-60x60.png"> + <link rel="apple-touch-icon" sizes="72x72" href="https://groups.io/img/org.1/favicons/apple-icon-72x72.png"> + <link rel="apple-touch-icon" sizes="76x76" href="https://groups.io/img/org.1/favicons/apple-icon-76x76.png"> + <link rel="apple-touch-icon" sizes="114x114" href="https://groups.io/img/org.1/favicons/apple-icon-114x114.png"> + <link rel="apple-touch-icon" sizes="120x120" href="https://groups.io/img/org.1/favicons/apple-icon-120x120.png"> + <link rel="apple-touch-icon" sizes="144x144" href="https://groups.io/img/org.1/favicons/apple-icon-144x144.png"> + <link rel="apple-touch-icon" sizes="152x152" href="https://groups.io/img/org.1/favicons/apple-icon-152x152.png"> + <link rel="apple-touch-icon" sizes="180x180" href="https://groups.io/img/org.1/favicons/apple-icon-180x180.png"> + <link rel="icon" type="image/png" sizes="192x192" href="../../../../img/org.1/favicons/android-icon-192x192.png"> + <link rel="icon" type="image/png" sizes="32x32" href="../../../../img/org.1/favicons/favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="96x96" href="../../../../img/org.1/favicons/favicon-96x96.png"> + <link rel="icon" type="image/png" sizes="16x16" href="../../../../img/org.1/favicons/favicon-16x16.png"> + <link rel="manifest" href="../../../../img/org.1/favicons/manifest.json"> + <meta name="msapplication-TileColor" content="#ffffff"> + <meta name="msapplication-TileImage" content="/ms-icon-144x144.png"> + + + + +<script> +/* stubs */ +const hapticsImpactHeavy = async () => { +}; +const hapticsImpactMedium = async () => { +}; +const hapticsImpactLight = async () => { +}; +const hapticsVibrate = async () => { +}; +const hapticsSelectionStart = async () => { +}; +const hapticsSelectionChanged = async () => { +}; +const hapticsSelectionEnd = async () => { +}; +</script> + + +<script> + + function setPullToRefresh() {} + + function gotoURL(inurl) { + window.location.href = inurl; + return; + } + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); + if (isHTMX == true) { + document.body.addEventListener('htmx:afterSettle', f, {once: true}); + } else { + if (document.readyState !== 'loading') { + console.log('document is already ready, just execute code here'); + f(); + } else { + console.log('document was not ready, place code here'); + document.addEventListener('DOMContentLoaded', f, {once: true}); + } + } + } + + // stub + function logError(data, url, linenumber) { + console.log(data) + return; + } + var pushSubToken; + var ignoreErrors = false; + var lastError = ""; + + window.onerror = function(errorMessage, errorUrl, errorLine, errorColumn, errorObj) { + let column; + let stack; + if (console && console.log) { + console.log("msg:", errorMessage); + console.log("url:", errorUrl); + console.log("line:", errorLine); + if (errorColumn !== undefined && errorObj != null) { + console.log("column:", errorColumn); + column = errorColumn; + } + if (errorObj !== undefined && errorObj != null) { + console.log("stack:", errorObj.stack); + stack = errorObj.stack; + } + console.log("client_id:", "web.web09.236792.1714523382009518856"); + console.log("last_error:", lastError); + console.log("stack:", stack); + } + if (errorUrl == "" || errorUrl === null) { + errorUrl = window.location.href; + } + if (errorMessage.includes("SecurityError:") == true) { + ignoreErrors = true; + } + if (ignoreErrors == true) { + console.log("cookies, disabled, ignoring"); + lastError = errorMessage; + return; + } + jQuery.ajax({ + type: 'POST', + url: '/jsclienterror', + data: { + msg: errorMessage, + url: errorUrl, + line: errorLine, + column: column, + stack: stack, + last_error: lastError, + client_id: "web.web09.236792.1714523382009518856" + }, + success: function() { + if (console && console.log) { + console.log('JS error report successful.'); + } + lastError = errorMessage; + }, + error: function() { + if (console && console.error) { + console.error('JS error report submission failed!'); + } + lastError = errorMessage; + } + }); + return true; + } + +</script> + + + <script src="../../../../tinymce-5.10.9/tinymce.min.js"></script> + <script src="../../../../js/browser-image-compression-2.0.2.min.js"></script> + <link href="../../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> + <script src="../../../../js/run_prettify.js"></script> + <title> + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

An article on pharmaceutical engineering says: Direct steam contact with the surface of the object to be sterilized is required for the steam to transfer its stored energy to the object. Without direct steam contact to all surfaces, the item will not be sterilized. The amount of energy stored in steam is much higher than dry air or water at the same temperature. From the saturated steam table mentioned above, one can see that it takes 419 kJ/kg (180 Btu/lb) to heat water from 0°C to 100°C (32°F to 212°F). This is the enthalpy of water (hl). It takes an additional 2,257 kJ/kg (970 Btu/lb) to create steam at atmospheric pressure (100°C or 212°F). This additional energy stored in the steam is the enthalpy of vaporization (he), and is the key to steam sterilization. In order for the steam to transfer its stored energy, it must condense on the surface of the object being sterilized.

+

The energy that article talks about is thermal energy. If you pour dry powder into a vial, seal the stopper and heat the vial, the heat is conducted from the glass into the powder quite slowly because heat conduction in unmoving dry powder (with air between particles) is slow. After half hour heating, part of the powder remains relatively cold, unsterilized. The sterilization time begins when everything is heated enough - it's why the talk about "energy transfer".

+

Thermal energy can be transferred by condensation of steam (as explained in the quote above) or by conduction, radiation or convection. Conduction is indeed quite slow. Convection of dry air transfers thermal energy not enough fast. However, the author of that article talks about a "steam autoclave" implying that the water boiling in one part of the autoclave is not in direct contact with the items intended to be sterilized. If a vial is submerged in boiling water, convection in boiling water transfers thermal energy into the vial very, very much faster. If the vial contains a solution instead of a dry powder, the solution inside the vial also convects, the thermal energy is quickly transferred to every part of the solution, so if you submerge the vial in water boiling in a 15 PSI (or 100 kPa) pressure cooker then entire solution in the vial is quickly heated to 121°C.

+

The XFS-260 autoclave I use is similar to a pressure cooker, but has two bowls. The inner bowl is made of thin stainless steel. I pour water into the outer bowl up to slightly above the bottom of the inner bowl, and pour water into the inner bowl too. So, vials are submerged in water boiling at 129°C (under pressure 24 PSI). Thermal energy is quickly transferred by convection into every part of the solution inside the vials.

+

Officially 121°C for 8 minutes is enough. 30 min is overkill and to be sure that the temperature 121°C is reached inside the vial too. For 100°C the theory says longer time is required, but the heat-resistant pathogenic bacteria (tetanus, botulism) are anaerobic, oxygen containing in the air inside the vial is a poison for them.

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/34293/189648.html b/groups.io/g/MTFHRT/wiki/34293/189648.html new file mode 100644 index 00000000..09a3c832 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/34293/189648.html @@ -0,0 +1,1360 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

An article on pharmaceutical engineering says: Direct steam contact with the surface of the object to be sterilized is required for the steam to transfer its stored energy to the object. Without direct steam contact to all surfaces, the item will not be sterilized. The amount of energy stored in steam is much higher than dry air or water at the same temperature. From the saturated steam table mentioned above, one can see that it takes 419 kJ/kg (180 Btu/lb) to heat water from 0°C to 100°C (32°F to 212°F). This is the enthalpy of water (hl). It takes an additional 2,257 kJ/kg (970 Btu/lb) to create steam at atmospheric pressure (100°C or 212°F). This additional energy stored in the steam is the enthalpy of vaporization (he), and is the key to steam sterilization. In order for the steam to transfer its stored energy, it must condense on the surface of the object being sterilized.

+

The energy that article talks about is thermal energy. If you pour dry powder into a vial, seal the stopper and heat the vial, the heat is conducted from the glass into the powder quite slowly because heat conduction in unmoving dry powder (with air between particles) is slow. After half hour heating, part of the powder remains relatively cold, unsterilized. The sterilization time begins when everything is heated enough - it's why the talk about "energy transfer".

+

Thermal energy can be transferred by condensation of steam (as explained in the quote above) or by conduction, radiation or convection. Conduction is indeed quite slow. Convection of dry air transfers thermal energy not enough fast. However, the author of that article talks about a "steam autoclave" implying that the water boiling in one part of the autoclave is not in direct contact with the items intended to be sterilized. If a vial is submerged in boiling water, convection in boiling water transfers thermal energy into the vial very, very much faster. If the vial contains a solution instead of a dry powder, the solution inside the vial also convects, the thermal energy is quickly transferred to every part of the solution, so if you submerge the vial in water boiling in a 15 PSI (or 100 kPa) pressure cooker then entire solution in the vial is quickly heated to 121°C.

+

The XFS-260 autoclave I use is similar to a pressure cooker, but has two bowls. The inner bowl is made of thin stainless steel. I pour water into the outer bowl up to slightly above the bottom of the inner bowl, and pour water into the inner bowl too. So, vials are submerged in water boiling at 129°C (under pressure 24 PSI). Thermal energy is quickly transferred by convection into every part of the solution inside the vials.

+

Officially 121°C for 8 minutes is enough. 30 min is overkill and to be sure that the temperature 121°C is reached inside the vial too. For 100°C the theory says longer time is required, but the heat-resistant pathogenic bacteria (tetanus, botulism) are anaerobic, oxygen containing in the air inside the vial is a poison for them.

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/34293/201261.html b/groups.io/g/MTFHRT/wiki/34293/201261.html new file mode 100644 index 00000000..93c4e6e5 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/34293/201261.html @@ -0,0 +1,1361 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

An article on pharmaceutical engineering says: Direct steam contact with the surface of the object to be sterilized is required for the steam to transfer its stored energy to the object. Without direct steam contact to all surfaces, the item will not be sterilized. The amount of energy stored in steam is much higher than dry air or water at the same temperature. From the saturated steam table mentioned above, one can see that it takes 419 kJ/kg (180 Btu/lb) to heat water from 0°C to 100°C (32°F to 212°F). This is the enthalpy of water (hl). It takes an additional 2,257 kJ/kg (970 Btu/lb) to create steam at atmospheric pressure (100°C or 212°F). This additional energy stored in the steam is the enthalpy of vaporization (he), and is the key to steam sterilization. In order for the steam to transfer its stored energy, it must condense on the surface of the object being sterilized.

+

The energy that article talks about is thermal energy. If you pour dry powder into a vial, seal the stopper and heat the vial, the heat is conducted from the glass into the powder quite slowly because heat conduction in unmoving dry powder (with air between particles) is slow. After half hour heating, part of the powder remains relatively cold, unsterilized. The sterilization time begins when everything is heated enough - it's why the talk about "energy transfer".

+

Thermal energy can be transferred by condensation of steam (as explained in the quote above) or by conduction, radiation or convection. Conduction is indeed quite slow. Convection of dry air transfers thermal energy not enough fast. However, the author of that article talks about a "steam autoclave" implying that the water boiling in one part of the autoclave is not in direct contact with the items intended to be sterilized. If a vial is submerged in boiling water, convection in boiling water transfers thermal energy into the vial very, very much faster. If the vial contains a solution instead of a dry powder, the solution inside the vial also convects, the thermal energy is quickly transferred to every part of the solution, so if you submerge the vial in water boiling in a 15 PSI (or 100 kPa) pressure cooker then entire solution in the vial is quickly heated to 121°C.

+

I was asked "how quickly?". I did an experiment with Castor oil (slow convection) and a digital thermometer with long thin sharp probe. I mixed 10 ml of solution with Castor oil and 2% benzyl alcohol in a vial, sealed and crimped the vial, pierced the rubber stopper with the probe (so that the thermo-sensitive end of the probe was at the center of the solution in the vial) and plunged the vial into water boiling in a pot. The numbers the thermometer indicated rose from 26°C to 95°C during 4.5 min. Then I cooled the probe in cold tap water to 16°C and plunged the probe directly into boiling water. The numbers rose to 95°C during 0.5 min (because the probe with metal coating has thermal inertia).

+

The XFS-260 autoclave I use is similar to a pressure cooker, but has two bowls. The inner bowl is made of thin stainless steel. I pour water into the outer bowl up to slightly above the bottom of the inner bowl, and pour water into the inner bowl too. So, vials are submerged in water boiling at 129°C (under pressure 24 PSI). Thermal energy is quickly transferred by convection into every part of the solution inside the vials.

+

Officially 121°C for 8 minutes is enough. Add 4 min for heat transfer into the vial. 30 min is overkill I added before the experiment to be sure that the temperature 121°C is reached inside the vial too. For 100°C the theory says longer time is required, but the heat-resistant pathogenic bacteria (tetanus, botulism) are anaerobic, oxygen containing in the air inside the vial is a poison for them, and the waterless solution is not nutritious for them (unlike canned meat).

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/34293/201262.html b/groups.io/g/MTFHRT/wiki/34293/201262.html new file mode 100644 index 00000000..6d103855 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/34293/201262.html @@ -0,0 +1,1361 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

An article on pharmaceutical engineering says: Direct steam contact with the surface of the object to be sterilized is required for the steam to transfer its stored energy to the object. Without direct steam contact to all surfaces, the item will not be sterilized. The amount of energy stored in steam is much higher than dry air or water at the same temperature. From the saturated steam table mentioned above, one can see that it takes 419 kJ/kg (180 Btu/lb) to heat water from 0°C to 100°C (32°F to 212°F). This is the enthalpy of water (hl). It takes an additional 2,257 kJ/kg (970 Btu/lb) to create steam at atmospheric pressure (100°C or 212°F). This additional energy stored in the steam is the enthalpy of vaporization (he), and is the key to steam sterilization. In order for the steam to transfer its stored energy, it must condense on the surface of the object being sterilized.

+

The energy that article talks about is thermal energy. If you pour dry powder into a vial, seal the stopper and heat the vial, the heat is conducted from the glass into the powder quite slowly because heat conduction in unmoving dry powder (with air between particles) is slow. After half hour heating, part of the powder remains relatively cold, unsterilized. The sterilization time begins when everything is heated enough - it's why the talk about "energy transfer".

+

Thermal energy can be transferred by condensation of steam (as explained in the quote above) or by conduction, radiation or convection. Conduction is indeed quite slow. Convection of dry air transfers thermal energy not enough fast. However, the author of that article talks about a "steam autoclave" implying that the water boiling in one part of the autoclave is not in direct contact with the items intended to be sterilized. If a vial is submerged in boiling water, convection in boiling water transfers thermal energy into the vial very, very much faster. If the vial contains a solution instead of a dry powder, the solution inside the vial also convects, the thermal energy is quickly transferred to every part of the solution, so if you submerge the vial in water boiling in a 15 PSI (or 100 kPa) pressure cooker then entire solution in the vial is quickly heated to 121°C.

+

I was asked "how quickly?". I did an experiment with viscous Castor oil (slow convection) and a digital thermometer with long thin sharp probe. I mixed 10 ml of solution with Castor oil and 2% benzyl alcohol in a vial, sealed and crimped the vial, pierced the rubber stopper with the probe (so that the thermo-sensitive end of the probe was at the center of the solution in the vial) and plunged the vial into water boiling in a pot. The numbers the thermometer indicated rose from 26°C to 95°C during 4.5 min. Then I cooled the probe in cold tap water to 16°C and plunged the probe directly into boiling water. The numbers rose to 95°C during 0.5 min (because the probe with metal coating has thermal inertia).

+

The XFS-260 autoclave I use is similar to a pressure cooker, but has two bowls. The inner bowl is made of thin stainless steel. I pour water into the outer bowl up to slightly above the bottom of the inner bowl, and pour water into the inner bowl too. So, vials are submerged in water boiling at 129°C (under pressure 24 PSI). Thermal energy is quickly transferred by convection into every part of the solution inside the vials.

+

Officially 121°C for 8 minutes is enough. Add 4 min for heat transfer into the vial. 30 min is overkill I added before the experiment to be sure that the temperature 121°C is reached inside the vial too. For 100°C the theory says longer time is required, but the heat-resistant pathogenic bacteria (tetanus, botulism) are anaerobic, oxygen containing in the air inside the vial is a poison for them, and the waterless solution is not nutritious for them (unlike canned meat).

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/34293/201265.html b/groups.io/g/MTFHRT/wiki/34293/201265.html new file mode 100644 index 00000000..bdb39f77 --- /dev/null +++ b/groups.io/g/MTFHRT/wiki/34293/201265.html @@ -0,0 +1,1361 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MTFHRT@groups.io | Wiki + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+
+
+
+
+ + + + + + Home + + + + + + + + + + + + + + + Messages + + + + + + + + + + + + + Hashtags + + + + + + + + + + + + + + + + + + + + + + + + + + + + Wiki + + + + + + + +
+
+ +
+
+ ctrl + shift + ? for shortcuts +
+ + +
+ © 2024 Groups.io +
+
+ +
+
+
+
+
+ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ Last edited + + · + + 5 revisions + +    + + + +
+ +
+
+ +
+
+ + +

An article on pharmaceutical engineering says: Direct steam contact with the surface of the object to be sterilized is required for the steam to transfer its stored energy to the object. Without direct steam contact to all surfaces, the item will not be sterilized. The amount of energy stored in steam is much higher than dry air or water at the same temperature. From the saturated steam table mentioned above, one can see that it takes 419 kJ/kg (180 Btu/lb) to heat water from 0°C to 100°C (32°F to 212°F). This is the enthalpy of water (hl). It takes an additional 2,257 kJ/kg (970 Btu/lb) to create steam at atmospheric pressure (100°C or 212°F). This additional energy stored in the steam is the enthalpy of vaporization (he), and is the key to steam sterilization. In order for the steam to transfer its stored energy, it must condense on the surface of the object being sterilized.

+

The energy that article talks about is thermal energy. If you pour dry powder into a vial, seal the stopper and heat the vial, the heat is conducted from the glass into the powder quite slowly because heat conduction in unmoving dry powder (with air between particles) is slow. After half hour heating, part of the powder remains relatively cold, unsterilized. The sterilization time begins when everything is heated enough - it's why the talk about "energy transfer".

+

Thermal energy can be transferred by condensation of steam (as explained in the quote above) or by conduction, radiation or convection. Conduction is indeed quite slow. Convection of dry air transfers thermal energy not enough fast. However, the author of that article talks about a "steam autoclave" implying that the water boiling in one part of the autoclave is not in direct contact with the items intended to be sterilized. If a vial is submerged in boiling water, convection in boiling water transfers thermal energy into the vial very, very much faster. If the vial contains a solution instead of a dry powder, the solution inside the vial also convects, the thermal energy is quickly transferred to every part of the solution, so if you submerge the vial in water boiling in a 15 PSI (or 100 kPa) pressure cooker then entire solution in the vial is quickly heated to 121°C.

+

I was asked "how quickly?". I did an experiment with viscous Castor oil (slow convection) and a digital thermometer with long thin sharp probe. I mixed 10 ml of solution with Castor oil and 2% benzyl alcohol in a vial, sealed and crimped the vial, pierced the rubber stopper with the probe (so that the thermo-sensitive end of the probe was at the center of the solution in the vial) and plunged most, but not all height of the vial into water boiling in a pot (so that the probe didn't touch the water). The numbers the thermometer indicated rose from 26°C to 95°C during 4.5 min. Then I cooled the probe in cold tap water to 16°C and plunged the probe directly into boiling water. The numbers rose to 95°C during 0.5 min (because the probe with metal coating has thermal inertia).

+

The XFS-260 autoclave I use is similar to a pressure cooker, but has two bowls. The inner bowl is made of thin stainless steel. I pour water into the outer bowl up to slightly above the bottom of the inner bowl, and pour water into the inner bowl too. So, vials are submerged in water boiling at 129°C (under pressure 24 PSI). Thermal energy is quickly transferred by convection into every part of the solution inside the vials.

+

Officially 121°C for 8 minutes is enough. Add 4 min for heat transfer into the vial. 30 min is overkill I added before the experiment to be sure that the temperature 121°C is reached inside the vial too. For 100°C the theory says longer time is required, but the heat-resistant pathogenic bacteria (tetanus, botulism) are anaerobic, oxygen containing in the air inside the vial is a poison for them, and the waterless solution is not nutritious for them (unlike canned meat).

+

+ + +

+ +
+
+
+ +
+
+ + + + +
+
+
+
+
+ +
+ + + + + + + + + + +
+ + + + + + + + + + + diff --git a/groups.io/g/MTFHRT/wiki/34293/history.html b/groups.io/g/MTFHRT/wiki/34293/history.html index f39ac7e6..77f5a29e 100644 --- a/groups.io/g/MTFHRT/wiki/34293/history.html +++ b/groups.io/g/MTFHRT/wiki/34293/history.html @@ -6,7 +6,7 @@ - + @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.774140.1713918440869044397"); + console.log("client_id:", "web.web09.236707.1714523380214868453"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.774140.1713918440869044397" + client_id: "web.web09.236707.1714523380214868453" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { - + - - + + @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -589,7 +914,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="201265"> + <a href="201265.html"> @@ -623,7 +948,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="201262"> + <a href="201262.html"> @@ -657,7 +982,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="201261"> + <a href="201261.html"> @@ -691,7 +1016,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="189648"> + <a href="189648.html"> @@ -725,7 +1050,7 @@ function createAlert(msg, isError, autoClose, noClose) { </td> <td> - <a href="189320"> + <a href="189320.html"> @@ -751,6 +1076,10 @@ function createAlert(msg, isError, autoClose, noClose) { </form> <script type="text/javascript"> +contentLoaded(false, function() { + + UpdateSidebar("wiki"); +}); function countChecked(id) { var checkedVal = 0; @@ -777,20 +1106,20 @@ function countChecked(id) { } </script> + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -800,9 +1129,7 @@ function countChecked(id) { </div> </div> - - @@ -831,48 +1158,43 @@ function countChecked(id) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -887,13 +1209,17 @@ function countChecked(id) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -915,7 +1241,7 @@ function countChecked(id) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -936,138 +1262,144 @@ function countChecked(id) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1089,6 +1421,21 @@ function countChecked(id) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/g/MTFHRT/wiki/index.html b/groups.io/g/MTFHRT/wiki/index.html index 4bba66c7..9bb86db6 100644 --- a/groups.io/g/MTFHRT/wiki/index.html +++ b/groups.io/g/MTFHRT/wiki/index.html @@ -6,7 +6,7 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="pinterest" content="nopin" /> <meta name="pinterest" content="nohover" /> @@ -59,9 +59,8 @@ const hapticsSelectionEnd = async () => { window.location.href = inurl; return; } - - function contentLoaded(isHTMX, f) { - console.log("contentLoaded: " + isHTMX); + function contentLoaded(isHTMX, f, caller = "") { + console.log("contentLoaded: " + isHTMX + " " + caller); if (isHTMX == true) { document.body.addEventListener('htmx:afterSettle', f, {once: true}); } else { @@ -99,8 +98,9 @@ const hapticsSelectionEnd = async () => { console.log("stack:", errorObj.stack); stack = errorObj.stack; } - console.log("client_id:", "web.web09.773957.1713918437143156791"); + console.log("client_id:", "web.web09.236474.1714523376224101645"); console.log("last_error:", lastError); + console.log("stack:", stack); } if (errorUrl == "" || errorUrl === null) { errorUrl = window.location.href; @@ -123,7 +123,7 @@ const hapticsSelectionEnd = async () => { column: column, stack: stack, last_error: lastError, - client_id: "web.web09.773957.1713918437143156791" + client_id: "web.web09.236474.1714523376224101645" }, success: function() { if (console && console.log) { @@ -144,10 +144,10 @@ const hapticsSelectionEnd = async () => { </script> - <script src="../../../tinymce-4.7.13/tinymce.min.js"></script> + <script src="../../../tinymce-5.10.9/tinymce.min.js"></script> <script src="../../../js/browser-image-compression-2.0.2.min.js"></script> - <link href="../../../css/application-e223b9cc72bae00ecc93c35c77a729b2.css" rel="stylesheet" id="groupsio-css"> - <script src="../../../js/application-6b3b1791facc58d99b1e9c143e69bd45.js" id="groupsio-js"></script> + <link href="../../../css/application-0fdc8fb7b212ef119ea05f76b6c42703.css" rel="stylesheet" id="groupsio-css"> + <script src="../../../js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js" id="groupsio-js"></script> <script src="../../../js/run_prettify.js"></script> <title> @@ -164,10 +164,24 @@ const hapticsSelectionEnd = async () => { +<script> + htmx.config.scrollBehavior = "instant"; + htmx.config.historyCacheSize = 0; + htmx.config.defaultSettleDelay = 0; + console.log("FULL PAGE LOAD"); +</script> </head> - <body class="fuelux" hx-headers='{"Accept-Version": "1ebf4951efb00d946a5fc7b821fff971e62f1ef8"}' hx-ext="preload"> + <body id="body" class="" hx-headers='{"Accept-Version": "7efa45c3c9d9df5d5c891fb6d7c86572635ba331"}' hx-ext="preload" hx-boost="false"> - <div class="navbar navbar-head" role="navigation" id="headerbar"> + <script> + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.body.classList.add('dark-mode'); + } + </script> + + + + <div class="navbar navbar-head navbar-fixed-top" role="navigation" id="headerbar"> <div class="container-fluid" style="padding-left:0px;"> <a href="https://groups.io" class="navbar-left"> <img src="../../../img/org.1/mainlogo.png" height="50" alt="Groups.io"> @@ -176,7 +190,6 @@ const hapticsSelectionEnd = async () => { <ul class="nav navbar-nav hidden-xs"> <li> <a href="https://groups.io/search"> - <i class="fa fa-search"></i> Find or Create a Group </a> </li> @@ -235,7 +248,6 @@ const hapticsSelectionEnd = async () => { </li> <li> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> Help </a> </li> @@ -279,7 +291,7 @@ const hapticsSelectionEnd = async () => { <li class="noborderitem list-group-item"> <a href="https://groups.io/helpcenter" target="_blank"> - <i class="fa-fw fa fa-info-circle"></i> + <i class="fa-fw fa fa-question-circle"></i> Help </a> </li> @@ -332,11 +344,151 @@ const hapticsSelectionEnd = async () => { </div> </div> +<script> +var groupnavigatorData = [ + +]; +</script> + + +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="groupnavigatorModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="groupnavigatorInput" placeholder="Go to group..." style="margin-bottom:10px"> + <div id="groupnavigatorContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + +<script> +// Keep track of the currently selected index +var selectedIndex = -1; + +// Function to highlight the matched substring +function highlightSubstring(str, substring) { + var index = str.toLowerCase().indexOf(substring.toLowerCase()); + if (index !== -1) { + var before = str.substring(0, index); + var middle = str.substring(index, index + substring.length); + var after = str.substring(index + substring.length); + return before + '<span class="autocomplete-highlight">' + middle + '</span>' + after; + } + return str; +} + +// Function to highlight the selected item and ensure it is visible in the scrollable list +function highlightSelectedItem(modalName) { + var listContainer = document.getElementById(modalName + 'Container'); + var items = document.getElementsByClassName(modalName + '-list-item'); + Array.from(items).forEach(function(item, idx) { + item.className = idx === selectedIndex ? modalName + '-list-item autocomplete-list-item btn-primary no-hover' : modalName + '-list-item autocomplete-list-item no-hover'; // Apply btn-primary class to the selected item + }); + if (items.length > 0 && selectedIndex >= 0) { + var selectedItem = items[selectedIndex]; + var containerTop = listContainer.scrollTop; + var containerBottom = containerTop + listContainer.clientHeight; + var itemTop = selectedItem.offsetTop; + var itemBottom = itemTop + selectedItem.offsetHeight; + const fudge = 59; + if (selectedIndex > 0 && itemTop > containerBottom) { + // If there are items below the selected item and the selected item is not fully visible, scroll down + listContainer.scrollTop = itemTop - listContainer.clientHeight + items[selectedIndex - 1].offsetHeight; + } else if (selectedIndex < items.length - 1 && (itemTop - fudge) < containerTop) { + // If there are items above the selected item and the selected item is not fully visible, scroll up + listContainer.scrollTop = itemTop - fudge - items[selectedIndex + 1].offsetHeight; + } + } +} + +// function to populate the list based on the input +function populateList(modalName, data) { + var input = document.getElementById(modalName+'Input').value; + var listContainer = document.getElementById(modalName+'Container'); + listContainer.innerHTML = ''; + data.forEach(function(item) { + if (item.name.toLowerCase().includes(input.toLowerCase())) { + var div = document.createElement('div'); + div.innerHTML = highlightSubstring(item.name, input); + div.className = modalName+'-list-item autocomplete-list-item no-hover'; // Apply no-hover class + div.addEventListener('click', function() { + // Navigate to the specified URL when a list item is clicked + window.location.href = item.url; + }); + div.addEventListener('mousemove', function() { + // Remove no-hover class from all items when the mouse is moved over any item + console.log("mouse move"); + var items = document.getElementsByClassName(modalName+'-list-item'); + Array.from(items).forEach(function(item) { + item.classList.remove('no-hover'); + }); + }); + listContainer.appendChild(div); + } + }); + highlightSelectedItem(modalName); +} + +function InitAutocomplete(modalName, data) { + // Focus the input field when the modal is shown and populate the list + $('#' + modalName + 'Modal').on('shown.bs.modal', function () { + $('#' + modalName + 'Input').focus().val(''); + populateList(modalName, data); + selectedIndex = 0; + highlightSelectedItem(modalName); + }); + + // Event listener for input field typing + document.getElementById(modalName + 'Input').addEventListener('input', function() { + populateList(modalName, data); + selectedIndex = 0; + }); + + // Event listener for arrow keys and enter key + document.getElementById(modalName + 'Input').addEventListener('keydown', function(event) { + var items = document.getElementsByClassName(modalName + '-list-item'); + if (event.key === 'ArrowDown') { + event.preventDefault(); + if (selectedIndex < items.length - 1) selectedIndex++; + highlightSelectedItem(modalName); + } else if (event.key === 'ArrowUp') { + event.preventDefault(); + if (selectedIndex > 0) selectedIndex--; + highlightSelectedItem(modalName); + } else if (event.key === 'Enter' && selectedIndex >= 0 && selectedIndex < items.length) { + event.preventDefault(); + items[selectedIndex].click(); + } + }); +} + +function showAutocompleteModal(modalName) { + $('#' + modalName + 'Modal').modal('show'); + selectedIndex = -1; +} +</script> + <div id="content" class="container-fluid"> <script> + InitAutocomplete("groupnavigator", groupnavigatorData); + + document.body.addEventListener("showReloadPageDialog", function(evt) { + $('#reloadPageModal').modal('show'); + }); + // submitEvent acts like .submit(), except it is compatible with the app, by using events instead. function submitEvent(ele) { console.log("in submitEvent"); + if (ele.startsWith('#')) { + ele = ele.slice(1); + } + document.getElementById(ele).submit(); + return; + /* const theEvent = new CustomEvent('submit', { bubbles: true, cancelable: true @@ -358,69 +510,204 @@ const hapticsSelectionEnd = async () => { console.log("calling submit"); ele.submit(); } + */ } // gioDestroy is a convenience function for destroy callbacks function gioDestroy(eventCB) { - document.body.addEventListener("htmx:beforeSwap", eventCB, { - once: true - }); - } - document.body.addEventListener('htmx:beforeSwap', function(evt) { - drawer = document.getElementById('drawer-name'); - if (drawer != null) { - drawerObj.closeDrawer(drawer); + let internalGioDestroy = function(evt) { + // do not activate on infinite scroll events + if (evt.detail.target !== undefined && evt.detail.target.id != "maincontent-refresh") { + console.log("Ignoring infinite scroll event"); + return; + } + console.log("Calling destroy callback"); + eventCB(evt); } - }); + document.body.addEventListener("htmx:beforeSwap", internalGioDestroy, {once: true}); + document.body.addEventListener("htmx:historyCacheMiss", internalGioDestroy, {once: true}); + } + + var drawerCloseFunc = function(evt) { + console.log("in drawerCloseFunc"); + // Find all elements with the class 'drawer' + var drawers = document.querySelectorAll('.drawer'); + + // Iterate over each element and call closeDrawer() on each + drawers.forEach(function(obj) { + drawerObj.closeDrawer(obj); + }); + $('.modal').modal('hide'); + } + document.body.addEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.addEventListener('htmx:historyCacheMiss', drawerCloseFunc); + + var keydownFunc = function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + if (event.key === 'Escape') { + event.target.blur(); + } + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + console.log("HERE: " + event.key + " " + event.ctrlKey + " " + event.shiftKey + " " + event.metaKey); + if (event.ctrlKey && event.shiftKey && (event.key === '?' || event.key === '/')) { + event.preventDefault(); // Prevent the default action + // Show the modal dialog for keyboard shortcuts + $('#shortcutModal').modal('show'); + return; + } + $('#shortcutModal').modal('hide'); + + if (event.key.toLowerCase() === 'g') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("groupnavigator"); + return; + } + } + } + + // Check if the pressed key is '/' + if ((event.key === 'f' || event.key === 'F') && event.shiftKey) { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + if (event.metaKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); // Prevent the default action + // Focus on the search box + let box = document.getElementById('searchbox') + if (box != null) { + document.getElementById('searchbox').focus(); + } + } + } + } + } + document.addEventListener('keydown', keydownFunc); + var removeDrawerCloseFunc = function(evt) { + document.body.removeEventListener('htmx:beforeSwap', drawerCloseFunc); + document.body.removeEventListener('htmx:historyCacheMiss', drawerCloseFunc); + document.removeEventListener('keydown', keydownFunc); + } + document.body.addEventListener("htmx:historyCacheMiss", removeDrawerCloseFunc, {once: true}); </script> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="shortcutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Keyboard Shortcuts</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-3 text-right"><strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Show all keyboard shortcuts</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>shift</strong> + <strong>f</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Find</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>g</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Navigate to a group</div> + </div> + <div class="row"> + <div class="col-xs-3 text-right"><strong class="ctrlmeta">ctrl</strong> + <strong>/</strong>  :</div> + <div class="col-xs-9" style="margin-left: -23px;">Quick actions</div> + </div> + </div> + <div class="text-center" style="margin-top:10px; margin-bottom:10px; font-size:12px;"><strong>esc</strong> to dismiss</div> + </div> + </div> +</div> +<!-- Modal Dialog for Keyboard Shortcuts --> +<div class="modal fade" id="reloadPageModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Update</h4> + </div> + <div class="modal-body"> + The website has been updated. Please click the button to reload the page. + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default btn-sm" data-dismiss="modal" onclick="javascript:location.reload()"> + Reload + </button> + </div> + </div> + </div> +</div> + - <div id="mainrow" class="row"> - <div class="col-md-3 col-lg-2 hidden-xs hidden-sm"> - <div class="list-group noborderlist"> - - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + <div id="mainrow" class="row" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > + <div id="groupsidebar" class="scrollbar hidden-print"> + <div class="scrollbar-content"> + <div id="accordion" role="tablist" aria-multiselectable="true" style="margin-bottom:20px;"> + <div class="list-group noborderlist panel" style="border:0;margin-bottom:0px"> + + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-badge" class="badge"></span> </a> - - - - - - - @@ -435,24 +722,63 @@ const hapticsSelectionEnd = async () => { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-badge" class="badge"></span> </a> + </div> + </div> + + <div class="text-center" style="font-size:13px;margin-bottom:30px"> + <div style="padding-bottom:10px;"> + <strong>ctrl</strong> + <strong>shift</strong> + <strong>?</strong> for shortcuts + </div> + <div style="padding-bottom:5px;"> + <a href="https://groups.io/static/about"> + About + </a> · + <a href="https://groups.io/static/features"> + Features + </a> · + <a href="https://groups.io/static/pricing"> + Pricing + </a> + </div> + <div style="padding-bottom:5px;"> + <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> + Updates + </a> · + <a href="https://groups.io/static/tos"> + Terms + </a> · + <a href="https://groups.io/helpcenter" target="_blank"> + Help + </a> + </div> + <div style="padding-bottom:5px;"> + © 2024 Groups.io + </div> + </div> + </div> </div> - <div id="maincontent" class="col-xs-12 col-sm-12 col-md-9 col-lg-10"> - <div id="maincontent-refresh"> - + <div id="maincontent" class="groupmaincontent"> + <div id="maincontent-refresh" style="height:100%"> + <div id="maincontent-column" class="col-xs-12 maincontent-column"> + @@ -460,8 +786,7 @@ const hapticsSelectionEnd = async () => { <div class="alert alert-info alert-dismissible" role="alert"> - We are pleased to announce several enhancements to the Groups.io web and app experience, which will be in effect starting Thursday, April 25th. - <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. + We are pleased to announce several enhancements to the Groups.io web and app experience. <a href="https://groups.io/static/newui" style="color:#333333">Click here</a> for more information. </div> @@ -535,27 +860,29 @@ function createAlert(msg, isError, autoClose, noClose) { -<form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> - - <div class="input-group"> - <input type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20"> - <div class="input-group-btn"> - <button class="btn btn-primary" type="submit"> - <span class="fa fa-search"></span> - </button> - </div> - </div> -</form> + <form class="form-inline pull-right hidden-xs" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + + + <div class="input-group"> + <input id="searchbox" type="text" class="form-control" placeholder="Search" title="Search" name="q" size="20" style="height:37px"> + <div class="input-group-btn"> + <button class="btn btn-primary" type="submit" style="height:37px;"> + <span class="fa fa-search"></span> + </button> + </div> + </div> + </form> -<span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> -<ol class="breadcrumb"> - <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> - <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> - <li class="active"><i class="fa fa-book"></i> Home</li> -</ol> - + <span class="hidden-sm hidden-md hidden-lg pull-right" style="padding:8px 15px;"><a data-toggle="modal" data-target="#searchModal"><i class="fa fa-search"></i></a></span> + <ol class="breadcrumb"> + <li class="hidden-xs"><a href="https://groups.io/g/MTFHRT"><i class="fa fa-home"></i> MTFHRT</a></li> + <li><a href="https://groups.io/g/MTFHRT/wiki"><i class="fa fa-book"></i> Wiki</a></li> + + <li class="active"><i class="fa fa-book"></i> Home</li> + </ol> + <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel"> <div class="modal-dialog" role="document"> @@ -574,6 +901,7 @@ function createAlert(msg, isError, autoClose, noClose) { </h4> </div> <form class="form-horizontal" method="get" action="https://groups.io/g/MTFHRT/wikisearch"> + <div class="modal-body"> <div class="form-group"> <div class="col-sm-12"> @@ -599,51 +927,9 @@ function createAlert(msg, isError, autoClose, noClose) { - - - <div class="pull-right"> - Last edited -<script id="timedispupdated30846"> - $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false - )); -</script> - · - <a href="30846/history.html"> - 5 revisions - </a> -    - <a href="30846.html"> - <i class="fa fa-link fa-lg"></i> - </a> - </div> - <p> -   - </p> - <br> - - <div class="row"> - <div class="col-sm-12"> - - <span class="visitedlinks"> - <p><a href="29602.html" rel="nofollow">Injections</a></p> -<p><a href="30843.html" rel="nofollow">Gel</a></p> -<p><a title="How to measure melting point of most organic powders using typical household items." href="32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> -<p>Literature and discussions on:</p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">hGH, igf-1 and effects on hrt</a></p> -<p>  <a href="https://groups.io/g/MTFHRT/topic/79606271" rel="nofollow">Hrt and brain</a></p> -<p> </p> -<p> </p> -<p> </p> - <p /> - </span> - - </div> - - </div> - <div class="row"> - <div class="col-sm-12"> - - <div class="hidden-print"> + <div class="row" style="margin-bottom:20px;"> + <div class="col-xs-12"> + <span class="hidden-print"> <div class="btn-group"> <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> Pages @@ -684,25 +970,74 @@ function createAlert(msg, isError, autoClose, noClose) { </ul> </div> - </div> + </span> + + + <div class="pull-right"> + Last edited +<script id="timedispupdated30846"> + $('#timedispupdated30846').replaceWith(DisplayShortTime(1666818091540635289, false + )); +</script> + · + <a href="30846/history.html"> + 5 revisions + </a> +    + <a href="30846.html"> + <i class="fa fa-link fa-lg"></i> + </a> + </div> + + </div> + </div> + + <div class="row"> + <div class="col-sm-12"> + + <span class="wikidisplay user-content"> + <p><a href="29602.html" rel="nofollow">Injections</a></p> +<p><a href="30843.html" rel="nofollow">Gel</a></p> +<p><a title="How to measure melting point of most organic powders using typical household items." href="32288.html" target="_blank" rel="nofollow noopener">How to measure melting point of most organic powders using typical household items.</a></p> +<p>Literature and discussions on:</p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/80225302" rel="nofollow">hGH, igf-1 and effects on hrt</a></p> +<p>  <a href="https://groups.io/g/MTFHRT/topic/79606271" rel="nofollow">Hrt and brain</a></p> +<p> </p> +<p> </p> +<p> </p> + <p /> + </span> + + </div> + + </div> + <div class="row"> + <div class="col-sm-12"> + </div> </div> +<script> +contentLoaded(false, function() { + UpdateSidebar("wiki"); +}); +</script> + + </div> </div> </div> </div> - <div class="row" id="mobileSidebar"> + <div class="row hidden-print" id="mobileSidebar" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div class="col-xs-12 hidden-md hidden-lg"> - <div class="navbar navbar-default navbar-fixed-bottom" id="groupsidebarendXX"> + <div class="navbar navbar-default navbar-fixed-bottom"> <div class="container" style="display: flex; justify-content: space-around;"> - - <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true"> + <div id="mobilesidebar-archives" class="mobilesidebar-item" style="margin-top:10px; padding-bottom:20px; flex: 1; text-align: center;" hx-get="https://groups.io/g/MTFHRT/topics?sidebar=true" hx-boost="true" hx-target="#maincontent-refresh" hx-push-url="true" hx-swap="innerHTML scroll:top" > <div style="display: inline-block; position: relative;"> <div style="position: relative;display: inline-block;"> <i class="fa-fw fa-light fa-comments fa-2x"></i> @@ -712,9 +1047,7 @@ function createAlert(msg, isError, autoClose, noClose) { </div> </div> - - @@ -743,48 +1076,43 @@ function createAlert(msg, isError, autoClose, noClose) { <div class="drawer__content"> <div class="list-group noborderlist"> - <a title="Group Home" href="https://groups.io/g/MTFHRT" class="noborderitem list-group-item sidebar-item"> + + + <a id="sidebar-home" title="Group Home" href="https://groups.io/g/MTFHRT" class="list-group-item sidebar-item"> <i class="fa-fw fa fa-home fa-lg"></i> Home </a> - + - - - <a title="Messages" href="https://groups.io/g/MTFHRT/topics" hx-get-disable="https://groups.io/g/MTFHRT/topics" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-archives" class="noborderitem list-group-item sidebar-item sidebar-archives"> + <a title="Messages" href="https://groups.io/g/MTFHRT/topics?sidebar=true" id="sidebar-archives-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-archives"> <i class="fa-fw fa fa-comments fa-lg"></i> Messages + <span id="sidebar-archives-mobile-badge" class="badge"></span> </a> - + + + - <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" hx-get-disable="https://groups.io/g/MTFHRT/hashtags" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-hashtags" class="noborderitem list-group-item sidebar-item sidebar-hashtags"> + <a title="Hashtags" href="https://groups.io/g/MTFHRT/hashtags" id="sidebar-hashtags-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-hashtags"> <i class="fa-fw fa fa-hashtag fa-lg"></i> Hashtags + <span id="sidebar-hashtags-mobile-badge" class="badge"></span> </a> - - - - - - - @@ -799,13 +1127,17 @@ function createAlert(msg, isError, autoClose, noClose) { + + + + - <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" hx-get-disable="https://groups.io/g/MTFHRT/wiki" preload hx-target="#maincontent-refresh" hx-push-url="true" - id="sidebar-wiki" class="noborderitem list-group-item sidebar-item sidebar-wiki active"> + <a title="Wiki" href="https://groups.io/g/MTFHRT/wiki" id="sidebar-wiki-mobile" class="noborderitem list-group-item sidebar-item sidebar-item-wiki active"> <i class="fa-fw fa fa-book fa-lg"></i> Wiki + <span id="sidebar-wiki-mobile-badge" class="badge"></span> </a> @@ -827,7 +1159,7 @@ function createAlert(msg, isError, autoClose, noClose) { </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/g/updates/messages?expanded=1"> <i class="fa-fw far fa-thermometer-three-quarters fa-lg"></i> - Updates + # Changelog </a> <a class="noborderitem list-group-item sidebar-item" href="https://groups.io/static/tos"> <i class="fa-fw fal fa-newspaper fa-lg"></i> @@ -848,138 +1180,144 @@ function createAlert(msg, isError, autoClose, noClose) { </section> </div> </div> -<script> - document.body.addEventListener("gio:keyboardWillShow", keyboardWillShow); - document.body.addEventListener("gio:keyboardWillHide", keyboardWillHide); - var restorePadding = false; - function keyboardWillShow() { - return; - $("#mobileSidebar").hide(); - // On narrow screens, we add a padding-bottom in groupsio.css to make room for the mobile sidebar. - // We need to remove this when we remove the mobile sidebar for the keyboard. And then - // we need to restore it afterwards. - let padding = $("#content").css("padding-bottom"); - console.log("padding-bottom is " + padding); - if (padding == "70px") { - $("#content").css("padding-bottom", "0px"); - console.log("REMOVING PADDING"); - restorePadding = true; - } - } - function keyboardWillHide() { - return; - $("#mobileSidebar").show(); - if (restorePadding == true) { - $("#content").css("padding-bottom", "70px"); - console.log("RESTORING PADDING"); - restorePadding = false; - } - } - document.body.addEventListener('htmx:beforeSend', function(evt) { - let id = evt.detail.elt.id; - if(id.startsWith("mobilesidebar-")) { - console.log(id + " was clicked"); - var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); - sidebarItems.forEach(function(item) { - var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; - console.log("ID:" + item.id); - if (item.id == id) { - console.log("making solid") - iElement.classList.add('fa-solid'); - iElement.classList.remove('fa-light'); - } else { - console.log("making light") - iElement.classList.remove('fa-solid'); - iElement.classList.add('fa-light'); - } - }); - } else if (id.startsWith("sidebar-")) { - var sidebarItems = document.querySelectorAll('.sidebar-item'); - // remove 'active' class from all 'sidebar-item' elements - sidebarItems.forEach(function(item) { - if (item.id == id) { - item.classList.add('active'); - } else { - item.classList.remove('active'); - } - }); - } +<!-- Modal Dialog for Autocomplete --> +<div class="modal fade" id="quickActionsModal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-body"> + <input type="text" class="form-control" id="quickActionsInput" placeholder="Go to page..." style="margin-bottom:10px"> + <div id="quickActionsContainer" class="autocompleteResults" style="max-height:250px; overflow-y: auto;"></div> + <div class="text-center" style="margin-top:10px; font-size:12px;"><i class="fa-sharp fa-arrow-up-arrow-down"></i> to navigate   <i class="fa-sharp fa-arrow-turn-down-left"></i> to use   <strong>esc</strong> to dismiss</div> + </div> + </div> + </div> +</div> + + + + +<script> + var quickActionsData = [ + + + {name: "Group Home", url: "https://groups.io/g/MTFHRT"}, + + + + {name: "Topics", url: "https://groups.io/g/MTFHRT/topics"}, + {name: "Messages", url: "https://groups.io/g/MTFHRT/messages"}, + {name: "Expanded Messages", url: "https://groups.io/g/MTFHRT/messages?expanded=1"}, + + + {name: "Polls", url: "https://groups.io/g/MTFHRT/polls"}, + + + {name: "Hashtags", url: "https://groups.io/g/MTFHRT/hashtags"}, + + + + + + + + + + + + + + + + {name: "Wiki", url: "https://groups.io/g/MTFHRT/wiki"}, + + + /* other pages */ + {name: "Help", url: "/helpcenter"}, + {name: "Feed", url: "/feed"}, + {name: "Your Groups", url: "/groups"}, + {name: "Your Calendar", url: "/calendar"}, + {name: "Your Activity", url: "/activity"}, + {name: "Your Pending Messages", url: "/pendingmsgs"}, + {name: "Account Login", url: "/account"}, + {name: "Account Preferences", url: "/account?page=prefs"}, + {name: "Account Security", url: "/account?page=security"}, + {name: "Account Identity", url: "/account?page=profile&member_info_id=0"}, + {name: "Account Notifications", url: "/account?page=notifications"}, + {name: "Account Other Services", url: "/account?page=oauth"}, + {name: "Account Bounces", url: "/account?page=bounces"}, + {name: "Account Billing", url: "/account?page=billing"}, + {name: "Find a Group", url: "/search?p=SubsCount,,,20,2,0,0"}, + ]; + + + InitAutocomplete("quickActions", quickActionsData); + + document.addEventListener('keydown', function(event) { + var tagName = event.target.tagName.toLowerCase(); + if (tagName === 'input' || tagName === 'textarea' || event.target.isContentEditable) { + return; + } + // check if the viewimages viewer is up + let element = document.getElementById('overlay'); + if (element && element.classList.contains('visible')) { + return; + } + if (event.key.toLowerCase() === '/') { + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + // For Mac + // Check if Command (event.metaKey) is pressed, and either Option (event.altKey) is pressed or not + if (event.metaKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } else { + // For Windows and Linux + if (event.ctrlKey) { + event.preventDefault(); + showAutocompleteModal("quickActions"); + return; + } + } + } }); + function UpdateSidebar(id) { + console.log(id + " was clicked"); + var sidebarItems = document.querySelectorAll('.mobilesidebar-item'); + sidebarItems.forEach(function(item) { + var iElement = item.getElementsByTagName('div')[0].getElementsByTagName('i')[0]; + if (item.id == "mobilesidebar-" + id) { + console.log("making solid " + id) + iElement.classList.add('fa-solid'); + iElement.classList.remove('fa-light'); + } else { + iElement.classList.remove('fa-solid'); + iElement.classList.add('fa-light'); + } + }); + var sidebarItems = document.querySelectorAll('.sidebar-item'); + // remove 'active' class from all 'sidebar-item' elements + sidebarItems.forEach(function(item) { + if (item.id == "sidebar-" + id) { + console.log("making active " + id) + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } </script> - <p></p> </div> <div id="scroll-top" class="scroll-top-wrapper hidden-xs"> <span class="scroll-top-inner"> - <i class="fa fa-arrow-circle-up fa-fw fa-2x" style="vertical-align:-.25em"></i> + <i class="fa fa-arrow-circle-up fa-fw fa-2x"></i> </span> </div> - <div class="hidden-xs hidden-sm" id="footer"> - <div class="navbar navbar-default"> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#footercollapse"> - <span class="sr-only"> - Toggle navigation - </span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - </div> - <div class="collapse navbar-collapse" id="footercollapse"> - <ul class="nav navbar-nav"> - - - <li> - <a href="https://groups.io/static/about"> - About - </a> - </li> - <li> - <a href="https://groups.io/static/features"> - Features - </a> - </li> - <li> - <a href="https://groups.io/static/pricing"> - Pricing - </a> - </li> - <li> - <a rel="nofollow" href="https://groups.io/g/updates/messages?expanded=1"> - Updates - </a> - </li> - - <li> - <a href="https://groups.io/static/tos"> - Terms - </a> - </li> - <li> - <a href="https://groups.io/helpcenter" target="_blank"> - Help - </a> - </li> - - </ul> - <ul class="nav navbar-nav navbar-right"> - <li> - <p class="navbar-text"> - © - <span class="hidden-sm"> - 2024 - </span> - Groups.io - </p> - </li> - </ul> - </div> - </div> - </div> + <script> $(function() { $(document).on('scroll', function() { @@ -1001,6 +1339,21 @@ function createAlert(msg, isError, autoClose, noClose) { scrollTop: offsetTop }, 100, 'linear'); } + + if (navigator.platform.toUpperCase().indexOf('MAC') >= 0) { + let elements = document.querySelectorAll('strong.ctrlmeta'); + elements.forEach((element) => { + // Check if the innerText is "ctrl" + if (element.innerText === 'ctrl') { + // Create a new "i" element + let newElement = document.createElement('i'); + newElement.classList.add('fa-solid', 'fa-command'); + + // Replace the old "strong" element with the new "i" element + element.parentNode.replaceChild(newElement, element); + } + }); + } </script> diff --git a/groups.io/js/application-6b3b1791facc58d99b1e9c143e69bd45.js b/groups.io/js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js similarity index 92% rename from groups.io/js/application-6b3b1791facc58d99b1e9c143e69bd45.js rename to groups.io/js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js index a439de7c..56b0890f 100644 --- a/groups.io/js/application-6b3b1791facc58d99b1e9c143e69bd45.js +++ b/groups.io/js/application-2fb8693374ebdea0ffcbb3b8c1d39910.js @@ -27,6 +27,14 @@ if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires j a._handler(e(window),"resize",function(){a._listenFullScreen(screen.width===window.innerWidth&&screen.height===window.innerHeight)}),i="webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange",a._handler(e(document),i,function(){a._listenFullScreen(t.checkFullScreen())}),a._autoFitContent(),a._initClickable(),a._refreshPreview()},_autoFitContent:function(){var t,i=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,a=this,r=400>i?a.previewSettingsSmall||a.defaults.previewSettingsSmall:a.previewSettings||a.defaults.previewSettings;e.each(r,function(e,i){t=".file-preview-frame .file-preview-"+e,a.$preview.find(t+".kv-preview-data,"+t+" .kv-preview-data").css(i)})},_scanDroppedItems:function(e,t,i){i=i||"";var a,r,n,o=this,l=function(e){o._log("Error scanning dropped files!"),o._log(e)};e.isFile?e.file(function(e){t.push(e)},l):e.isDirectory&&(r=e.createReader(),(n=function(){r.readEntries(function(r){if(r&&r.length>0){for(a=0;a<r.length;a++)o._scanDroppedItems(r[a],t,i+e.name+"/");n()}return null},l)})())},_initDragDrop:function(){var t=this,i=t.$dropZone;t.dropZoneEnabled&&t.showPreview&&(t._handler(i,"dragenter dragover",e.proxy(t._zoneDragEnter,t)),t._handler(i,"dragleave",e.proxy(t._zoneDragLeave,t)),t._handler(i,"drop",e.proxy(t._zoneDrop,t)),t._handler(e(document),"dragenter dragover drop",t._zoneDragDropInit))},_zoneDragDropInit:function(e){e.stopPropagation(),e.preventDefault()},_zoneDragEnter:function(i){var a=this,r=i.originalEvent.dataTransfer,n=e.inArray("Files",r.types)>-1;return a._zoneDragDropInit(i),a.isDisabled||!n?(i.originalEvent.dataTransfer.effectAllowed="none",void(i.originalEvent.dataTransfer.dropEffect="none")):void(a._raise("fileDragEnter",{sourceEvent:i,files:r.types.Files})&&t.addCss(a.$dropZone,"file-highlighted"))},_zoneDragLeave:function(e){var t=this;t._zoneDragDropInit(e),t.isDisabled||t._raise("fileDragLeave",{sourceEvent:e})&&t.$dropZone.removeClass("file-highlighted")},_zoneDrop:function(e){var i,a=this,r=a.$element,n=e.originalEvent.dataTransfer,o=n.files,l=n.items,s=t.getDragDropFolders(l),d=function(){a.isAjaxUpload?a._change(e,o):(a.changeTriggered=!0,r.get(0).files=o,setTimeout(function(){a.changeTriggered=!1,r.trigger("change"+a.namespace)},10)),a.$dropZone.removeClass("file-highlighted")};if(e.preventDefault(),!a.isDisabled&&!t.isEmpty(o)&&a._raise("fileDragDrop",{sourceEvent:e,files:o}))if(s>0){if(!a.isAjaxUpload)return void a._showFolderError(s);for(o=[],i=0;i<l.length;i++){var c=l[i].webkitGetAsEntry();c&&a._scanDroppedItems(c,o)}setTimeout(function(){d()},500)}else d()},_uploadClick:function(e){var i,a=this,r=a.$container.find(".fileinput-upload"),n=!r.hasClass("disabled")&&t.isEmpty(r.attr("disabled"));if(!e||!e.isDefaultPrevented()){if(!a.isAjaxUpload)return void(n&&"submit"!==r.attr("type")&&(i=r.closest("form"),i.length&&i.trigger("submit"),e.preventDefault()));e.preventDefault(),n&&a.upload()}},_submitForm:function(){var e=this;return e._isFileSelectionValid()&&!e._abort({})},_clearPreview:function(){var i=this,a=i.$preview,r=i.showUploadedThumbs?i.getFrames(":not(.file-preview-success)"):i.getFrames();r.each(function(){var i=e(this);i.remove(),t.cleanZoomCache(a.find("#zoom-"+i.attr("id")))}),i.getFrames().length&&i.showPreview||i._resetUpload(),i._validateDefaultPreview()},_initSortable:function(){var i,a=this,r=a.$preview,n="."+t.SORT_CSS,o=a.reversePreviewOrder;window.KvSortable&&0!==r.find(n).length&&(i={handle:".drag-handle-init",dataIdAttr:"data-preview-id",scroll:!1,draggable:n,onSort:function(i){var r=i.oldIndex,n=i.newIndex,l=0;a.initialPreview=t.moveArray(a.initialPreview,r,n,o),a.initialPreviewConfig=t.moveArray(a.initialPreviewConfig,r,n,o),a.previewCache.init(),a.getFrames(".file-preview-initial").each(function(){e(this).attr("data-fileindex","init_"+l),l++}),a._raise("filesorted",{previewId:e(i.item).attr("id"),oldIndex:r,newIndex:n,stack:a.initialPreviewConfig})}},r.data("kvsortable")&&r.kvsortable("destroy"),e.extend(!0,i,a.fileActionSettings.dragSettings),r.kvsortable(i))},_setPreviewContent:function(e){var t=this;t.$preview.html(e),t._autoFitContent()},_initPreview:function(e){var i,a=this,r=a.initialCaption||"";return a.previewCache.count()?(i=a.previewCache.out(),r=e&&a.initialCaption?a.initialCaption:i.caption,a._setPreviewContent(i.content),a._setInitThumbAttr(),a._setCaption(r),a._initSortable(),void(t.isEmpty(i.content)||a.$container.removeClass("file-input-new"))):(a._clearPreview(),void(e?a._setCaption(r):a._initCaption()))},_getZoomButton:function(e){var t=this,i=t.previewZoomButtonIcons[e],a=t.previewZoomButtonClasses[e],r=' title="'+(t.previewZoomButtonTitles[e]||"")+'" ',n=r+("close"===e?' data-dismiss="modal" aria-hidden="true"':"");return"fullscreen"!==e&&"borderless"!==e&&"toggleheader"!==e||(n+=' data-toggle="button" aria-pressed="false" autocomplete="off"'),'<button type="button" class="'+a+" btn-"+e+'"'+n+">"+i+"</button>"},_getModalContent:function(){var e=this;return e._getLayoutTemplate("modal").setTokens({rtl:e.rtl?" kv-rtl":"",zoomFrameClass:e.frameClass,heading:e.msgZoomModalHeading,prev:e._getZoomButton("prev"),next:e._getZoomButton("next"),toggleheader:e._getZoomButton("toggleheader"),fullscreen:e._getZoomButton("fullscreen"),borderless:e._getZoomButton("borderless"),close:e._getZoomButton("close")})},_listenModalEvent:function(e){var i=this,a=i.$modal,r=function(e){return{sourceEvent:e,previewId:a.data("previewId"),modal:a}};a.on(e+".bs.modal",function(n){var o=a.find(".btn-fullscreen"),l=a.find(".btn-borderless");i._raise("filezoom"+e,r(n)),"shown"===e&&(l.removeClass("active").attr("aria-pressed","false"),o.removeClass("active").attr("aria-pressed","false"),a.hasClass("file-zoom-fullscreen")&&(i._maximizeZoomDialog(),t.checkFullScreen()?o.addClass("active").attr("aria-pressed","true"):l.addClass("active").attr("aria-pressed","true")))})},_initZoom:function(){var i,a=this,r=a._getLayoutTemplate("modalMain"),n="#"+t.MODAL_ID;a.showPreview&&(a.$modal=e(n),a.$modal&&a.$modal.length||(i=e(document.createElement("div")).html(r).insertAfter(a.$container),a.$modal=e(n).insertBefore(i),i.remove()),t.initModal(a.$modal),a.$modal.html(a._getModalContent()),e.each(t.MODAL_EVENTS,function(e,t){a._listenModalEvent(t)}))},_initZoomButtons:function(){var t,i,a=this,r=a.$modal.data("previewId")||"",n=a.getFrames().toArray(),o=n.length,l=a.$modal.find(".btn-prev"),s=a.$modal.find(".btn-next");return n.length<2?(l.hide(),void s.hide()):(l.show(),s.show(),void(o&&(t=e(n[0]),i=e(n[o-1]),l.removeAttr("disabled"),s.removeAttr("disabled"),t.length&&t.attr("id")===r&&l.attr("disabled",!0),i.length&&i.attr("id")===r&&s.attr("disabled",!0))))},_maximizeZoomDialog:function(){var t=this,i=t.$modal,a=i.find(".modal-header:visible"),r=i.find(".modal-footer:visible"),n=i.find(".modal-body"),o=e(window).height(),l=0;i.addClass("file-zoom-fullscreen"),a&&a.length&&(o-=a.outerHeight(!0)),r&&r.length&&(o-=r.outerHeight(!0)),n&&n.length&&(l=n.outerHeight(!0)-n.height(),o-=l),i.find(".kv-zoom-body").height(o)},_resizeZoomDialog:function(e){var i=this,a=i.$modal,r=a.find(".btn-fullscreen"),n=a.find(".btn-borderless");if(a.hasClass("file-zoom-fullscreen"))t.toggleFullScreen(!1),e?r.hasClass("active")||(a.removeClass("file-zoom-fullscreen"),i._resizeZoomDialog(!0),n.hasClass("active")&&n.removeClass("active").attr("aria-pressed","false")):r.hasClass("active")?r.removeClass("active").attr("aria-pressed","false"):(a.removeClass("file-zoom-fullscreen"),i.$modal.find(".kv-zoom-body").css("height",i.zoomModalHeight));else{if(!e)return void i._maximizeZoomDialog();t.toggleFullScreen(!0)}a.focus()},_setZoomContent:function(i,a){var r,n,o,l,s,d,c,p,u,f,m=this,v=i.attr("id"),g=m.$preview.find("#zoom-"+v),h=m.$modal,w=h.find(".btn-fullscreen"),_=h.find(".btn-borderless"),b=h.find(".btn-toggleheader");n=g.attr("data-template")||"generic",r=g.find(".kv-file-content"),o=r.length?r.html():"",u=i.data("caption")||"",f=i.data("size")||"",l=u+" "+f,h.find(".kv-zoom-title").attr("title",e("<div/>").html(l).text()).html(l),s=h.find(".kv-zoom-body"),h.removeClass("kv-single-content"),a?(p=s.addClass("file-thumb-loading").clone().insertAfter(s),s.html(o).hide(),p.fadeOut("fast",function(){s.fadeIn("fast",function(){s.removeClass("file-thumb-loading")}),p.remove()})):s.html(o),c=m.previewZoomSettings[n],c&&(d=s.find(".kv-preview-data"),t.addCss(d,"file-zoom-detail"),e.each(c,function(e,t){d.css(e,t),(d.attr("width")&&"width"===e||d.attr("height")&&"height"===e)&&d.removeAttr(e)})),h.data("previewId",v),m._handler(h.find(".btn-prev"),"click",function(){m._zoomSlideShow("prev",v)}),m._handler(h.find(".btn-next"),"click",function(){m._zoomSlideShow("next",v)}),m._handler(w,"click",function(){m._resizeZoomDialog(!0)}),m._handler(_,"click",function(){m._resizeZoomDialog(!1)}),m._handler(b,"click",function(){var e,t=h.find(".modal-header"),i=h.find(".modal-body .floating-buttons"),a=t.find(".kv-zoom-actions"),r=function(e){var i=m.$modal.find(".kv-zoom-body"),a=m.zoomModalHeight;h.hasClass("file-zoom-fullscreen")&&(a=i.outerHeight(!0),e||(a-=t.outerHeight(!0))),i.css("height",e?a+e:a)};t.is(":visible")?(e=t.outerHeight(!0),t.slideUp("slow",function(){a.find(".btn").appendTo(i),r(e)})):(i.find(".btn").appendTo(a),t.slideDown("slow",function(){r()})),h.focus()}),m._handler(h,"keydown",function(t){var i=t.which||t.keyCode,a=e(this).find(".btn-prev"),r=e(this).find(".btn-next"),n=e(this).data("previewId"),o=m.rtl?39:37,l=m.rtl?37:39;i===o&&a.length&&!a.attr("disabled")&&m._zoomSlideShow("prev",n),i===l&&r.length&&!r.attr("disabled")&&m._zoomSlideShow("next",n)})},_zoomPreview:function(e){var i,a=this,r=a.$modal;if(!e.length)throw"Cannot zoom to detailed preview!";t.initModal(r),r.html(a._getModalContent()),i=e.closest(t.FRAMES),a._setZoomContent(i),r.modal("show"),a._initZoomButtons()},_zoomSlideShow:function(t,i){var a,r,n,o=this,l=o.$modal.find(".kv-zoom-actions .btn-"+t),s=o.getFrames().toArray(),d=s.length;if(!l.attr("disabled")){for(r=0;d>r;r++)if(e(s[r]).attr("id")===i){n="prev"===t?r-1:r+1;break}0>n||n>=d||!s[n]||(a=e(s[n]),a.length&&o._setZoomContent(a,!0),o._initZoomButtons(),o._raise("filezoom"+t,{previewId:i,modal:o.$modal}))}},_initZoomButton:function(){var t=this;t.$preview.find(".kv-file-zoom").each(function(){var i=e(this);t._handler(i,"click",function(){t._zoomPreview(i)})})},_inputFileCount:function(){return this.$element.get(0).files.length},_refreshPreview:function(){var e,t=this;t._inputFileCount()&&t.showPreview&&t.isPreviewable&&(t.isAjaxUpload?(e=t.getFileStack(),t.filestack=[],e.length?t._clearFileInput():e=t.$element.get(0).files):e=t.$element.get(0).files,e&&e.length&&(t.readFiles(e),t._setFileDropZoneTitle()))},_clearObjects:function(t){t.find("video audio").each(function(){this.pause(),e(this).remove()}),t.find("img object div").each(function(){e(this).remove()})},_clearFileInput:function(){var t,i,a,r=this,n=r.$element;r._inputFileCount()&&(t=n.closest("form"),i=e(document.createElement("form")),a=e(document.createElement("div")),n.before(a),t.length?t.after(i):a.after(i),i.append(n).trigger("reset"),a.before(n).remove(),i.remove())},_resetUpload:function(){var e=this;e.uploadCache={content:[],config:[],tags:[],append:!0},e.uploadCount=0,e.uploadStatus={},e.uploadLog=[],e.uploadAsyncCount=0,e.loadedImages=[],e.totalImagesCount=0,e.$btnUpload.removeAttr("disabled"),e._setProgress(0),e.$progress.hide(),e._resetErrors(!1),e.ajaxAborted=!1,e.ajaxRequests=[],e._resetCanvas(),e.cacheInitialPreview={},e.overwriteInitial&&(e.initialPreview=[],e.initialPreviewConfig=[],e.initialPreviewThumbTags=[],e.previewCache.data={content:[],config:[],tags:[]})},_resetCanvas:function(){var e=this;e.canvas&&e.imageCanvasContext&&e.imageCanvasContext.clearRect(0,0,e.canvas.width,e.canvas.height)},_hasInitialPreview:function(){var e=this;return!e.overwriteInitial&&e.previewCache.count()},_resetPreview:function(){var e,t,i=this;i.previewCache.count()?(e=i.previewCache.out(),i._setPreviewContent(e.content),i._setInitThumbAttr(),t=i.initialCaption?i.initialCaption:e.caption,i._setCaption(t)):(i._clearPreview(),i._initCaption()),i.showPreview&&(i._initZoom(),i._initSortable())},_clearDefaultPreview:function(){var e=this;e.$preview.find(".file-default-preview").remove()},_validateDefaultPreview:function(){var e=this;e.showPreview&&!t.isEmpty(e.defaultPreviewContent)&&(e._setPreviewContent('<div class="file-default-preview">'+e.defaultPreviewContent+"</div>"),e.$container.removeClass("file-input-new"),e._initClickable())},_resetPreviewThumbs:function(e){var t,i=this;return e?(i._clearPreview(),void i.clearStack()):void(i._hasInitialPreview()?(t=i.previewCache.out(),i._setPreviewContent(t.content),i._setInitThumbAttr(),i._setCaption(t.caption),i._initPreviewActions()):i._clearPreview())},_getLayoutTemplate:function(e){var i=this,a=i.layoutTemplates[e];return t.isEmpty(i.customLayoutTags)?a:t.replaceTags(a,i.customLayoutTags)},_getPreviewTemplate:function(e){var i=this,a=i.previewTemplates[e];return t.isEmpty(i.customPreviewTags)?a:t.replaceTags(a,i.customPreviewTags)},_getOutData:function(e,t,i){var a=this;return e=e||{},t=t||{},i=i||a.filestack.slice(0)||{},{form:a.formdata,files:i,filenames:a.filenames,filescount:a.getFilesCount(),extra:a._getExtraData(),response:t,reader:a.reader,jqXHR:e}},_getMsgSelected:function(e){var t=this,i=1===e?t.fileSingle:t.filePlural;return e>0?t.msgSelected.replace("{n}",e).replace("{files}",i):t.msgNoFilesSelected},_getFrame:function(t){var i=this,a=e("#"+t);return a.length?a:(i._log('Invalid thumb frame with id: "'+t+'".'),null)},_getThumbs:function(e){return e=e||"",this.getFrames(":not(.file-preview-initial)"+e)},_getExtraData:function(e,t){var i=this,a=i.uploadExtraData;return"function"==typeof i.uploadExtraData&&(a=i.uploadExtraData(e,t)),a},_initXhr:function(e,t,i){var a=this;return e.upload&&e.upload.addEventListener("progress",function(e){var r=0,n=e.total,o=e.loaded||e.position;e.lengthComputable&&(r=Math.floor(o/n*100)),t?a._setAsyncUploadStatus(t,r,i):a._setProgress(r)},!1),e},_initAjaxSettings:function(){var t=this;t._ajaxSettings=e.extend(!0,{},t.ajaxSettings),t._ajaxDeleteSettings=e.extend(!0,{},t.ajaxDeleteSettings)},_mergeAjaxCallback:function(e,t,i){var a,r=this,n=r._ajaxSettings,o=r.mergeAjaxCallbacks;"delete"===i&&(n=r._ajaxDeleteSettings,o=r.mergeAjaxDeleteCallbacks),a=n[e],o&&"function"==typeof a?"before"===o?n[e]=function(){a.apply(this,arguments),t.apply(this,arguments)}:n[e]=function(){t.apply(this,arguments),a.apply(this,arguments)}:n[e]=t},_ajaxSubmit:function(t,i,a,r,n,o){var l,s,d=this;d._raise("filepreajax",[n,o])&&(d._uploadExtra(n,o),d._initAjaxSettings(),d._mergeAjaxCallback("beforeSend",t),d._mergeAjaxCallback("success",i),d._mergeAjaxCallback("complete",a),d._mergeAjaxCallback("error",r),s=o&&d.uploadUrlThumb?d.uploadUrlThumb:d.uploadUrl,l=e.extend(!0,{},{xhr:function(){var t=e.ajaxSettings.xhr();return d._initXhr(t,n,d.getFileStack().length)},url:d._encodeURI(s),type:"POST",dataType:"json",data:d.formdata,cache:!1,processData:!1,contentType:!1},d._ajaxSettings),d.ajaxRequests.push(e.ajax(l)))},_mergeArray:function(e,i){var a=this,r=t.cleanArray(a[e]),n=t.cleanArray(i);a[e]=r.concat(n)},_initUploadSuccess:function(i,a,r){var n,o,l,s,d,c,p,u,f,m=this;m.showPreview&&"object"==typeof i&&!e.isEmptyObject(i)&&void 0!==i.initialPreview&&i.initialPreview.length>0&&(m.hasInitData=!0,c=i.initialPreview||[],p=i.initialPreviewConfig||[],u=i.initialPreviewThumbTags||[],n=void 0===i.append||i.append,c.length>0&&!t.isArray(c)&&(c=c.split(m.initialPreviewDelimiter)),m._mergeArray("initialPreview",c),m._mergeArray("initialPreviewConfig",p),m._mergeArray("initialPreviewThumbTags",u),void 0!==a?r?(f=a.attr("data-fileindex"),m.uploadCache.content[f]=c[0],m.uploadCache.config[f]=p[0]||[],m.uploadCache.tags[f]=u[0]||[],m.uploadCache.append=n):(l=m.previewCache.add(c,p[0],u[0],n),o=m.previewCache.get(l,!1),s=e(document.createElement("div")).html(o).hide().insertAfter(a),d=s.find(".kv-zoom-cache"),d&&d.length&&d.insertAfter(a),a.fadeOut("slow",function(){var e=s.find(".file-preview-frame");e&&e.length&&e.insertBefore(a).fadeIn("slow").css("display:inline-block"),m._initPreviewActions(),m._clearFileInput(),t.cleanZoomCache(m.$preview.find("#zoom-"+a.attr("id"))),a.remove(),s.remove(),m._initSortable()})):(m.previewCache.set(c,p,u,n),m._initPreview(),m._initPreviewActions()))},_initSuccessThumbs:function(){var i=this;i.showPreview&&i._getThumbs(t.FRAMES+".file-preview-success").each(function(){var a=e(this),r=i.$preview,n=a.find(".kv-file-remove");n.removeAttr("disabled"),i._handler(n,"click",function(){var e=a.attr("id"),n=i._raise("filesuccessremove",[e,a.attr("data-fileindex")]);t.cleanMemory(a),n!==!1&&a.fadeOut("slow",function(){t.cleanZoomCache(r.find("#zoom-"+e)),a.remove(),i.getFrames().length||i.reset()})})})},_checkAsyncComplete:function(){var t,i,a=this;for(i=0;i<a.filestack.length;i++)if(a.filestack[i]&&(t=a.previewInitId+"-"+i,-1===e.inArray(t,a.uploadLog)))return!1;return a.uploadAsyncCount===a.uploadLog.length},_uploadExtra:function(t,i){var a=this,r=a._getExtraData(t,i);0!==r.length&&e.each(r,function(e,t){a.formdata.append(e,t)})},_uploadSingle:function(i,a){var r,n,o,l,s,d,c,p,u,f,m,v=this,g=v.getFileStack().length,h=new FormData,w=v.previewInitId+"-"+i,_=v.filestack.length>0||!e.isEmptyObject(v.uploadExtraData),b=e("#"+w).find(".file-thumb-progress"),C={id:w,index:i};v.formdata=h,v.showPreview&&(n=e("#"+w+":not(.file-preview-initial)"),l=n.find(".kv-file-upload"),s=n.find(".kv-file-remove"),b.show()),0===g||!_||l&&l.hasClass("disabled")||v._abort(C)||(m=function(e,t){d||v.updateStack(e,void 0),v.uploadLog.push(t),v._checkAsyncComplete()&&(v.fileBatchCompleted=!0)},o=function(){var e,i,a,r=v.uploadCache,n=0,o=v.cacheInitialPreview;v.fileBatchCompleted&&(o&&o.content&&(n=o.content.length),setTimeout(function(){var l=0===v.getFileStack(!0).length;if(v.showPreview){if(v.previewCache.set(r.content,r.config,r.tags,r.append),n){for(i=0;i<r.content.length;i++)a=i+n,o.content[a]=r.content[i],o.config.length&&(o.config[a]=r.config[i]),o.tags.length&&(o.tags[a]=r.tags[i]);v.initialPreview=t.cleanArray(o.content),v.initialPreviewConfig=t.cleanArray(o.config),v.initialPreviewThumbTags=t.cleanArray(o.tags)}else v.initialPreview=r.content,v.initialPreviewConfig=r.config,v.initialPreviewThumbTags=r.tags;v.cacheInitialPreview={},v.hasInitData&&(v._initPreview(),v._initPreviewActions())}v.unlock(l),l&&v._clearFileInput(),e=v.$preview.find(".file-preview-initial"),v.uploadAsync&&e.length&&(t.addCss(e,t.SORT_CSS),v._initSortable()),v._raise("filebatchuploadcomplete",[v.filestack,v._getExtraData()]),v.uploadCount=0,v.uploadStatus={},v.uploadLog=[],v._setProgress(101),v.ajaxAborted=!1},100))},c=function(o){r=v._getOutData(o),v.fileBatchCompleted=!1,a||(v.ajaxAborted=!1),v.showPreview&&(n.hasClass("file-preview-success")||(v._setThumbStatus(n,"Loading"),t.addCss(n,"file-uploading")),l.attr("disabled",!0),s.attr("disabled",!0)),a||v.lock(),v._raise("filepreupload",[r,w,i]),e.extend(!0,C,r),v._abort(C)&&(o.abort(),a||(v._setThumbStatus(n,"New"),n.removeClass("file-uploading"),l.removeAttr("disabled"),s.removeAttr("disabled"),v.unlock()),v._setProgressCancelled())},p=function(o,s,c){var p=v.showPreview&&n.attr("id")?n.attr("id"):w;r=v._getOutData(c,o),e.extend(!0,C,r),setTimeout(function(){t.isEmpty(o)||t.isEmpty(o.error)?(v.showPreview&&(v._setThumbStatus(n,"Success"),l.hide(),v._initUploadSuccess(o,n,a),v._setProgress(101,b)),v._raise("fileuploaded",[r,p,i]),a?m(i,p):v.updateStack(i,void 0)):(d=!0,v._showUploadError(o.error,C),v._setPreviewError(n,i,v.filestack[i],v.retryErrorUploads),v.retryErrorUploads||l.hide(),a&&m(i,p),v._setProgress(101,e("#"+p).find(".file-thumb-progress"),v.msgUploadError))},100)},u=function(){setTimeout(function(){v.showPreview&&(l.removeAttr("disabled"),s.removeAttr("disabled"),n.removeClass("file-uploading")),a?o():(v.unlock(!1),v._clearFileInput()),v._initSuccessThumbs()},100)},f=function(t,r,o){var s=v.ajaxOperations.uploadThumb,c=v._parseError(s,t,o,a&&v.filestack[i].name?v.filestack[i].name:null);d=!0,setTimeout(function(){a&&m(i,w),v.uploadStatus[w]=100,v._setPreviewError(n,i,v.filestack[i],v.retryErrorUploads),v.retryErrorUploads||l.hide(),e.extend(!0,C,v._getOutData(t)),v._setProgress(101,b,v.msgAjaxProgressError.replace("{operation}",s)),v._setProgress(101,e("#"+w).find(".file-thumb-progress"),v.msgUploadError),v._showUploadError(c,C)},100)},h.append(v.uploadFileAttr,v.filestack[i],v.filenames[i]),h.append("file_id",i),v._ajaxSubmit(c,p,u,f,w,i))},_uploadBatch:function(){var i,a,r,n,o,l=this,s=l.filestack,d=s.length,c={},p=l.filestack.length>0||!e.isEmptyObject(l.uploadExtraData);l.formdata=new FormData,0!==d&&p&&!l._abort(c)&&(o=function(){e.each(s,function(e){l.updateStack(e,void 0)}),l._clearFileInput()},i=function(i){l.lock();var a=l._getOutData(i);l.ajaxAborted=!1,l.showPreview&&l._getThumbs().each(function(){var i=e(this),a=i.find(".kv-file-upload"),r=i.find(".kv-file-remove");i.hasClass("file-preview-success")||(l._setThumbStatus(i,"Loading"),t.addCss(i,"file-uploading")),a.attr("disabled",!0),r.attr("disabled",!0)}),l._raise("filebatchpreupload",[a]),l._abort(a)&&(i.abort(),l._getThumbs().each(function(){var t=e(this),i=t.find(".kv-file-upload"),a=t.find(".kv-file-remove");t.hasClass("file-preview-loading")&&(l._setThumbStatus(t,"New"),t.removeClass("file-uploading")),i.removeAttr("disabled"),a.removeAttr("disabled")}),l._setProgressCancelled())},a=function(i,a,r){var n=l._getOutData(r,i),s=0,d=l._getThumbs(":not(.file-preview-success)"),c=t.isEmpty(i)||t.isEmpty(i.errorkeys)?[]:i.errorkeys;t.isEmpty(i)||t.isEmpty(i.error)?(l._raise("filebatchuploadsuccess",[n]),o(),l.showPreview?(d.each(function(){var t=e(this);l._setThumbStatus(t,"Success"),t.removeClass("file-uploading"),t.find(".kv-file-upload").hide().removeAttr("disabled")}),l._initUploadSuccess(i)):l.reset(),l._setProgress(101)):(l.showPreview&&(d.each(function(){var t=e(this),i=t.attr("data-fileindex");t.removeClass("file-uploading"),t.find(".kv-file-upload").removeAttr("disabled"),t.find(".kv-file-remove").removeAttr("disabled"),0===c.length||-1!==e.inArray(s,c)?(l._setPreviewError(t,i,l.filestack[i],l.retryErrorUploads),l.retryErrorUploads||(t.find(".kv-file-upload").hide(),l.updateStack(i,void 0))):(t.find(".kv-file-upload").hide(),l._setThumbStatus(t,"Success"),l.updateStack(i,void 0)),t.hasClass("file-preview-error")&&!l.retryErrorUploads||s++}),l._initUploadSuccess(i)),l._showUploadError(i.error,n,"filebatchuploaderror"),l._setProgress(101,l.$progress,l.msgUploadError))},n=function(){l.unlock(),l._initSuccessThumbs(),l._clearFileInput(),l._raise("filebatchuploadcomplete",[l.filestack,l._getExtraData()])},r=function(t,i,a){var r=l._getOutData(t),n=l.ajaxOperations.uploadBatch,o=l._parseError(n,t,a);l._showUploadError(o,r,"filebatchuploaderror"),l.uploadFileCount=d-1,l.showPreview&&(l._getThumbs().each(function(){var t=e(this),i=t.attr("data-fileindex");t.removeClass("file-uploading"),void 0!==l.filestack[i]&&l._setPreviewError(t)}),l._getThumbs().removeClass("file-uploading"),l._getThumbs(" .kv-file-upload").removeAttr("disabled"),l._getThumbs(" .kv-file-delete").removeAttr("disabled"),l._setProgress(101,l.$progress,l.msgAjaxProgressError.replace("{operation}",n)))},e.each(s,function(e,i){t.isEmpty(s[e])||l.formdata.append(l.uploadFileAttr,i,l.filenames[e])}),l._ajaxSubmit(i,a,n,r))},_uploadExtraOnly:function(){var e,i,a,r,n=this,o={};n.formdata=new FormData,n._abort(o)||(e=function(e){n.lock();var t=n._getOutData(e);n._raise("filebatchpreupload",[t]),n._setProgress(50),o.data=t,o.xhr=e,n._abort(o)&&(e.abort(),n._setProgressCancelled())},i=function(e,i,a){var r=n._getOutData(a,e);t.isEmpty(e)||t.isEmpty(e.error)?(n._raise("filebatchuploadsuccess",[r]),n._clearFileInput(),n._initUploadSuccess(e),n._setProgress(101)):n._showUploadError(e.error,r,"filebatchuploaderror")},a=function(){n.unlock(),n._clearFileInput(),n._raise("filebatchuploadcomplete",[n.filestack,n._getExtraData()])},r=function(e,t,i){var a=n._getOutData(e),r=n.ajaxOperations.uploadExtra,l=n._parseError(r,e,i);o.data=a,n._showUploadError(l,a,"filebatchuploaderror"),n._setProgress(101,n.$progress,n.msgAjaxProgressError.replace("{operation}",r))},n._ajaxSubmit(e,i,a,r))},_deleteFileIndex:function(i){var a=this,r=i.attr("data-fileindex"),n=a.reversePreviewOrder;"init_"===r.substring(0,5)&&(r=parseInt(r.replace("init_","")),a.initialPreview=t.spliceArray(a.initialPreview,r,n),a.initialPreviewConfig=t.spliceArray(a.initialPreviewConfig,r,n),a.initialPreviewThumbTags=t.spliceArray(a.initialPreviewThumbTags,r,n),a.getFrames().each(function(){var t=e(this),i=t.attr("data-fileindex");"init_"===i.substring(0,5)&&(i=parseInt(i.replace("init_","")),i>r&&(i--,t.attr("data-fileindex","init_"+i)))}),a.uploadAsync&&(a.cacheInitialPreview=a.getPreview()))},_initFileActions:function(){var i=this,a=i.$preview;i.showPreview&&(i._initZoomButton(),i.getFrames(" .kv-file-remove").each(function(){var r,n,o,l,s=e(this),d=s.closest(t.FRAMES),c=d.attr("id"),p=d.attr("data-fileindex");i._handler(s,"click",function(){return l=i._raise("filepreremove",[c,p]),l!==!1&&i._validateMinCount()?(r=d.hasClass("file-preview-error"),t.cleanMemory(d),void d.fadeOut("slow",function(){t.cleanZoomCache(a.find("#zoom-"+c)),i.updateStack(p,void 0),i._clearObjects(d),d.remove(),c&&r&&i.$errorContainer.find('li[data-file-id="'+c+'"]').fadeOut("fast",function(){e(this).remove(),i._errorsExist()||i._resetErrors()}),i._clearFileInput();var l=i.getFileStack(!0),s=i.previewCache.count(),u=l.length,f=i.showPreview&&i.getFrames().length;0!==u||0!==s||f?(n=s+u,o=n>1?i._getMsgSelected(n):l[0]?i._getFileNames()[0]:"",i._setCaption(o)):i.reset(),i._raise("fileremoved",[c,p])})):!1})}),i.getFrames(" .kv-file-upload").each(function(){var a=e(this);i._handler(a,"click",function(){var e=a.closest(t.FRAMES),r=e.attr("data-fileindex");i.$progress.hide(),e.hasClass("file-preview-error")&&!i.retryErrorUploads||i._uploadSingle(r,!1)})}))},_initPreviewActions:function(){var i=this,a=i.$preview,r=i.deleteExtraData||{},n=t.FRAMES+" .kv-file-remove",o=i.fileActionSettings,l=o.removeClass,s=o.removeErrorClass,d=function(){var e=i.isAjaxUpload?i.previewCache.count():i._inputFileCount();a.find(t.FRAMES).length||e||(i._setCaption(""),i.reset(),i.initialCaption="")};i._initZoomButton(),a.find(n).each(function(){var n,o,c,p=e(this),u=p.data("url")||i.deleteUrl,f=p.data("key");if(!t.isEmpty(u)&&void 0!==f){var m,v,g,h,w=p.closest(t.FRAMES),_=i.previewCache.data,b=w.attr("data-fileindex");b=parseInt(b.replace("init_","")),g=t.isEmpty(_.config)&&t.isEmpty(_.config[b])?null:_.config[b],h=t.isEmpty(g)||t.isEmpty(g.extra)?r:g.extra,"function"==typeof h&&(h=h()),v={id:p.attr("id"),key:f,extra:h},n=function(e){i.ajaxAborted=!1,i._raise("filepredelete",[f,e,h]),i._abort()?e.abort():(p.removeClass(s),t.addCss(w,"file-uploading"),t.addCss(p,"disabled "+l))},o=function(e,r,n){var o,c;return t.isEmpty(e)||t.isEmpty(e.error)?(w.removeClass("file-uploading").addClass("file-deleted"),void w.fadeOut("slow",function(){b=parseInt(w.attr("data-fileindex").replace("init_","")),i.previewCache.unset(b),i._deleteFileIndex(w),o=i.previewCache.count(),c=o>0?i._getMsgSelected(o):"",i._setCaption(c),i._raise("filedeleted",[f,n,h]),t.cleanZoomCache(a.find("#zoom-"+w.attr("id"))),i._clearObjects(w),w.remove(),d()})):(v.jqXHR=n,v.response=e,i._showError(e.error,v,"filedeleteerror"),w.removeClass("file-uploading"),p.removeClass("disabled "+l).addClass(s),void d())},c=function(e,t,a){var r=i.ajaxOperations.deleteThumb,n=i._parseError(r,e,a);v.jqXHR=e,v.response={},i._showError(n,v,"filedeleteerror"),w.removeClass("file-uploading"),p.removeClass("disabled "+l).addClass(s),d()},i._initAjaxSettings(),i._mergeAjaxCallback("beforeSend",n,"delete"),i._mergeAjaxCallback("success",o,"delete"),i._mergeAjaxCallback("error",c,"delete"),m=e.extend(!0,{},{url:i._encodeURI(u),type:"POST",dataType:"json",data:e.extend(!0,{},{key:f},h)},i._ajaxDeleteSettings),i._handler(p,"click",function(){return i._validateMinCount()?(i.ajaxAborted=!1,i._raise("filebeforedelete",[f,h]),void(i.ajaxAborted instanceof Promise?i.ajaxAborted.then(function(t){t||e.ajax(m)}):i.ajaxAborted||e.ajax(m))):!1})}})},_hideFileIcon:function(){var e=this;e.overwriteInitial&&e.$captionContainer.removeClass("icon-visible")},_showFileIcon:function(){var e=this;t.addCss(e.$captionContainer,"icon-visible")},_getSize:function(t){var i,a,r,n=this,o=parseFloat(t),l=n.fileSizeGetter;return e.isNumeric(t)&&e.isNumeric(o)?("function"==typeof l?r=l(o):0===o?r="0.00 B":(i=Math.floor(Math.log(o)/Math.log(1024)),a=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],r=1*(o/Math.pow(1024,i)).toFixed(2)+" "+a[i]),n._getLayoutTemplate("size").replace("{sizeText}",r)):""},_getFileType:function(e){var t=this;return t.mimeTypeAliases[e]||e},_generatePreviewTemplate:function(i,a,r,n,o,l,s,d,c,p,u){var f,m,v=this,g=v.slug(r),h="",w="",_=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,b=400>_?v.previewSettingsSmall[i]||v.defaults.previewSettingsSmall[i]:v.previewSettings[i]||v.defaults.previewSettings[i],C=c||v._renderFileFooter(g,s,"auto",l),y=v._getPreviewIcon(r),x="type-default",T=y&&v.preferIconicPreview,E=y&&v.preferIconicZoomPreview;return b&&e.each(b,function(e,t){w+=e+":"+t+";"}),m=function(a,l,s,c){var f=s?"zoom-"+o:o,m=v._getPreviewTemplate(a),h=(d||"")+" "+c;return v.frameClass&&(h=v.frameClass+" "+h),s&&(h=h.replace(" "+t.SORT_CSS,"")),m=v._parseFilePreviewIcon(m,r),"text"===a&&(l=t.htmlEncode(l)),"object"!==i||n||e.each(v.defaults.fileTypeSettings,function(e,t){"object"!==e&&"other"!==e&&t(r,n)&&(x="type-"+e)}),m.setTokens({previewId:f,caption:g,frameClass:h,type:v._getFileType(n),fileindex:p,typeCss:x,footer:C,data:l,template:u||i,style:w?'style="'+w+'"':""})},p=p||o.slice(o.lastIndexOf("-")+1),v.fileActionSettings.showZoom&&(h=m(E?"other":i,a,!0,"kv-zoom-thumb")),h="\n"+v._getLayoutTemplate("zoomCache").replace("{zoomContent}",h),f=m(T?"other":i,a,!1,"kv-preview-thumb"),f+h},_addToPreview:function(e,t){var i=this;return i.reversePreviewOrder?e.prepend(t):e.append(t)},_previewDefault:function(i,a,r){var n=this,o=n.$preview;if(n.showPreview){var l,s=i?i.name:"",d=i?i.type:"",c=i.size||0,p=n.slug(s),u=r===!0&&!n.isAjaxUpload,f=t.createObjectURL(i);n._clearDefaultPreview(),l=n._generatePreviewTemplate("other",f,s,d,a,u,c),n._addToPreview(o,l),n._setThumbAttr(a,p,c),r===!0&&n.isAjaxUpload&&n._setThumbStatus(e("#"+a),"Error")}},_previewFile:function(e,t,i,a,r,n){if(this.showPreview){var o,l=this,s=t?t.name:"",d=n.type,c=n.name,p=l._parseFileType(d,s),u=l.allowedPreviewTypes,f=l.allowedPreviewMimeTypes,m=l.$preview,v=t.size||0,g=u&&u.indexOf(p)>=0,h=f&&-1!==f.indexOf(d),w="text"===p||"html"===p||"image"===p?i.target.result:r;if("html"===p&&l.purifyHtml&&window.DOMPurify&&(w=window.DOMPurify.sanitize(w)),g||h){o=l._generatePreviewTemplate(p,w,s,d,a,!1,v),l._clearDefaultPreview(),l._addToPreview(m,o);var _=m.find("#"+a+" img");l._validateImageOrientation(_,t,a,c,d,v,w)}else l._previewDefault(t,a);l._setThumbAttr(a,c,v),l._initSortable()}},_setThumbAttr:function(t,i,a){var r=this,n=e("#"+t);n.length&&(a=a&&a>0?r._getSize(a):"",n.data({caption:i,size:a}))},_setInitThumbAttr:function(){var e,i,a,r,n=this,o=n.previewCache.data,l=n.previewCache.count();if(0!==l)for(var s=0;l>s;s++)e=o.config[s],r=n.previewInitId+"-init_"+s,i=t.ifSet("caption",e,t.ifSet("filename",e)),a=t.ifSet("size",e),n._setThumbAttr(r,i,a)},_slugDefault:function(e){return t.isEmpty(e)?"":String(e).replace(/[\[\]\/\{}:;#%=\(\)\*\+\?\\\^\$\|<>&"']/g,"_")},_updateFileDetails:function(e){var i=this,a=i.$element,r=i.getFileStack(),n=t.isIE(9)&&t.findFileName(a.val())||a[0].files[0]&&a[0].files[0].name||r.length&&r[0].name||"",o=i.slug(n),l=i.isAjaxUpload?r.length:e,s=i.previewCache.count()+l,d=1===l?o:i._getMsgSelected(s);i.isError?(i.$previewContainer.removeClass("file-thumb-loading"), i.$previewStatus.html(""),i.$captionContainer.removeClass("icon-visible")):i._showFileIcon(),i._setCaption(d,i.isError),i.$container.removeClass("file-input-new file-input-ajax-new"),1===arguments.length&&i._raise("fileselect",[e,o]),i.previewCache.count()&&i._initPreviewActions()},_setThumbStatus:function(e,t){var i=this;if(i.showPreview){var a="indicator"+t,r=a+"Title",n="file-preview-"+t.toLowerCase(),o=e.find(".file-upload-indicator"),l=i.fileActionSettings;e.removeClass("file-preview-success file-preview-error file-preview-loading"),"Success"===t&&e.find(".file-drag-handle").remove(),o.html(l[a]),o.attr("title",l[r]),e.addClass(n),"Error"!==t||i.retryErrorUploads||e.find(".kv-file-upload").attr("disabled",!0)}},_setProgressCancelled:function(){var e=this;e._setProgress(101,e.$progress,e.msgCancelled)},_setProgress:function(e,i,a){var r,n=this,o=Math.min(e,100),l=n.progressUploadThreshold,s=100>=e?n.progressTemplate:n.progressCompleteTemplate,d=100>o?n.progressTemplate:a?n.progressErrorTemplate:s;i=i||n.$progress,t.isEmpty(d)||(r=l&&o>l&&100>=e?d.setTokens({percent:l,status:n.msgUploadThreshold}):d.setTokens({percent:o,status:e>100?n.msgUploadEnd:o+"%"}),i.html(r),a&&i.find('[role="progressbar"]').html(a))},_setFileDropZoneTitle:function(){var e,i=this,a=i.$container.find(".file-drop-zone"),r=i.dropZoneTitle;i.isClickable&&(e=t.isEmpty(i.$element.attr("multiple"))?i.fileSingle:i.filePlural,r+=i.dropZoneClickTitle.replace("{files}",e)),a.find("."+i.dropZoneTitleClass).remove(),!i.showPreview||0===a.length||i.getFileStack().length>0||!i.dropZoneEnabled||!i.isAjaxUpload&&i.$element.files||(0===a.find(t.FRAMES).length&&t.isEmpty(i.defaultPreviewContent)&&a.prepend('<div class="'+i.dropZoneTitleClass+'">'+r+"</div>"),i.$container.removeClass("file-input-new"),t.addCss(i.$container,"file-input-ajax-new"))},_setAsyncUploadStatus:function(t,i,a){var r=this,n=0;r._setProgress(i,e("#"+t).find(".file-thumb-progress")),r.uploadStatus[t]=i,e.each(r.uploadStatus,function(e,t){n+=t}),r._setProgress(Math.floor(n/a))},_validateMinCount:function(){var e=this,t=e.isAjaxUpload?e.getFileStack().length:e._inputFileCount();return e.validateInitialCount&&e.minFileCount>0&&e._getFileCount(t-1)<e.minFileCount?(e._noFilesError({}),!1):!0},_getFileCount:function(e){var t=this,i=0;return t.validateInitialCount&&!t.overwriteInitial&&(i=t.previewCache.count(),e+=i),e},_getFileId:function(e){var t,i=this,a=i.generateFileId;return"function"==typeof a?a(e,event):e?(t=String(e.webkitRelativePath||e.fileName||e.name||null),t?e.size+"-"+t.replace(/[^0-9a-zA-Z_-]/gim,""):null):null},_getFileName:function(e){return e&&e.name?this.slug(e.name):void 0},_getFileIds:function(e){var t=this;return t.fileids.filter(function(t){return e?void 0!==t:void 0!==t&&null!==t})},_getFileNames:function(e){var t=this;return t.filenames.filter(function(t){return e?void 0!==t:void 0!==t&&null!==t})},_setPreviewError:function(e,t,i,a){var r=this;if(void 0!==t&&r.updateStack(t,i),r.showPreview){if(r.removeFromPreviewOnError&&!a)return void e.remove();r._setThumbStatus(e,"Error"),r._refreshUploadButton(e,a)}},_refreshUploadButton:function(e,t){var i=this,a=e.find(".kv-file-upload"),r=i.fileActionSettings,n=r.uploadIcon,o=r.uploadTitle;a.length&&(t&&(n=r.uploadRetryIcon,o=r.uploadRetryTitle),a.attr("title",o).html(n))},_checkDimensions:function(e,i,a,r,n,o,l){var s,d,c,p,u=this,f="Small"===i?"min":"max",m=u[f+"Image"+o];!t.isEmpty(m)&&a.length&&(c=a[0],d="Width"===o?c.naturalWidth||c.width:c.naturalHeight||c.height,p="Small"===i?d>=m:m>=d,p||(s=u["msgImage"+o+i].setTokens({name:n,size:m}),u._showUploadError(s,l),u._setPreviewError(r,e,null)))},_getExifObj:function(e){var t=this,i=null;try{i=window.piexif?window.piexif.load(e):null}catch(a){i=null}return i||t._log("Error loading the piexif.js library."),i},_validateImageOrientation:function(e,i,a,r,n,o,l){var s,d,c=this;return s=e.length&&c.autoOrientImage?c._getExifObj(l):null,(d=s?s["0th"][piexif.ImageIFD.Orientation]:null)?(t.setImageOrientation(e,c.$preview.find("#zoom-"+a+" img"),d),c._raise("fileimageoriented",{$img:e,file:i}),void c._validateImage(a,r,n,o,l,s)):void c._validateImage(a,r,n,o,l,s)},_validateImage:function(t,i,a,r,n,o){var l,s,d,c=this,p=c.$preview,u=p.find("#"+t),f=u.attr("data-fileindex"),m=u.find("img");i=i||"Untitled",m.one("load",function(){s=u.width(),d=p.width(),s>d&&m.css("width","100%"),l={ind:f,id:t},c._checkDimensions(f,"Small",m,u,i,"Width",l),c._checkDimensions(f,"Small",m,u,i,"Height",l),c.resizeImage||(c._checkDimensions(f,"Large",m,u,i,"Width",l),c._checkDimensions(f,"Large",m,u,i,"Height",l)),c._raise("fileimageloaded",[t]),c.loadedImages.push({ind:f,img:m,thumb:u,pid:t,typ:a,siz:r,validated:!1,imgData:n,exifObj:o}),u.data("exif",o),c._validateAllImages()}).one("error",function(){c._raise("fileimageloaderror",[t])}).each(function(){this.complete?e(this).trigger("load"):this.error&&e(this).trigger("error")})},_validateAllImages:function(){var e,t,i,a=this,r={val:0},n=a.loadedImages.length,o=a.resizeIfSizeMoreThan;if(n===a.totalImagesCount&&(a._raise("fileimagesloaded"),a.resizeImage))for(e=0;e<a.loadedImages.length;e++)t=a.loadedImages[e],t.validated||(i=t.siz,i&&i>1e3*o&&a._getResizedImage(t,r,n),a.loadedImages[e].validated=!0)},_getResizedImage:function(i,a,r){var n,o,l,s,d,c,p,u=this,f=e(i.img)[0],m=f.naturalWidth,v=f.naturalHeight,g=1,h=u.maxImageWidth||m,w=u.maxImageHeight||v,_=!(!m||!v),b=u.imageCanvas,C=u.imageCanvasContext,y=i.typ,x=i.pid,T=i.ind,E=i.thumb,S=i.exifObj;if(d=function(e,t,i){u.isAjaxUpload?u._showUploadError(e,t,i):u._showError(e,t,i),u._setPreviewError(E,T)},(!u.filestack[T]||!_||h>=m&&w>=v)&&(_&&u.filestack[T]&&u._raise("fileimageresized",[x,T]),a.val++,a.val===r&&u._raise("fileimagesresized"),!_))return void d(u.msgImageResizeError,{id:x,index:T},"fileimageresizeerror");y=y||u.resizeDefaultImageType,o=m>h,l=v>w,g="width"===u.resizePreference?o?h/m:l?w/v:1:l?w/v:o?h/m:1,u._resetCanvas(),m*=g,v*=g,b.width=m,b.height=v;try{C.drawImage(f,0,0,m,v),s=b.toDataURL(y,u.resizeQuality),S&&(p=window.piexif.dump(S),s=window.piexif.insert(p,s)),n=t.dataURI2Blob(s),u.filestack[T]=n,u._raise("fileimageresized",[x,T]),a.val++,a.val===r&&u._raise("fileimagesresized",[void 0,void 0]),n instanceof Blob||d(u.msgImageResizeError,{id:x,index:T},"fileimageresizeerror")}catch(k){a.val++,a.val===r&&u._raise("fileimagesresized",[void 0,void 0]),c=u.msgImageResizeException.replace("{errors}",k.message),d(c,{id:x,index:T},"fileimageresizeexception")}},_initBrowse:function(e){var i=this,a=i.$element;i.showBrowse?i.$btnFile=e.find(".btn-file").append(a):(a.appendTo(e).attr("tabindex",-1),t.addCss(a,"file-no-browse"))},_initClickable:function(){var i,a,r=this;r.isClickable&&(i=r.$dropZone,r.isAjaxUpload||(a=r.$preview.find(".file-default-preview"),a.length&&(i=a)),t.addCss(i,"clickable"),i.attr("tabindex",-1),r._handler(i,"click",function(t){var a=e(t.target);e(r.elErrorContainer+":visible").length||a.parents(".file-preview-thumbnails").length&&!a.parents(".file-default-preview").length||(r.$element.data("zoneClicked",!0).trigger("click"),i.blur())}))},_initCaption:function(){var e=this,i=e.initialCaption||"";return e.overwriteInitial||t.isEmpty(i)?(e.$caption.val(""),!1):(e._setCaption(i),!0)},_setCaption:function(i,a){var r,n,o,l,s,d=this,c=d.getFileStack();if(d.$caption.length){if(d.$captionContainer.removeClass("icon-visible"),a)r=e("<div>"+d.msgValidationError+"</div>").text(),l=c.length,s=l?1===l&&c[0]?d._getFileNames()[0]:d._getMsgSelected(l):d._getMsgSelected(d.msgNo),n=t.isEmpty(i)?s:i,o='<span class="'+d.msgValidationErrorClass+'">'+d.msgValidationErrorIcon+"</span>";else{if(t.isEmpty(i))return;r=e("<div>"+i+"</div>").text(),n=r,o=d._getLayoutTemplate("fileIcon")}d.$captionContainer.addClass("icon-visible"),d.$caption.attr("title",r).val(n),d.$captionIcon.html(o)}},_createContainer:function(){var t=this,i={"class":"file-input file-input-new"+(t.rtl?" kv-rtl":"")},a=e(document.createElement("div")).attr(i).html(t._renderMain());return a.insertBefore(t.$element),t._initBrowse(a),t.theme&&a.addClass("theme-"+t.theme),a},_refreshContainer:function(){var e=this,t=e.$container,i=e.$element;i.insertAfter(t),t.html(e._renderMain()),e._initBrowse(t),e._validateDisabled()},_validateDisabled:function(){var e=this;e.$caption.attr({readonly:e.isDisabled})},_renderMain:function(){var e=this,t=e.dropZoneEnabled?" file-drop-zone":"file-drop-disabled",i=e.showClose?e._getLayoutTemplate("close"):"",a=e.showPreview?e._getLayoutTemplate("preview").setTokens({"class":e.previewClass,dropClass:t}):"",r=e.isDisabled?e.captionClass+" file-caption-disabled":e.captionClass,n=e.captionTemplate.setTokens({"class":r+" kv-fileinput-caption"});return e.mainTemplate.setTokens({"class":e.mainClass+(!e.showBrowse&&e.showCaption?" no-browse":""),preview:a,close:i,caption:n,upload:e._renderButton("upload"),remove:e._renderButton("remove"),cancel:e._renderButton("cancel"),browse:e._renderButton("browse")})},_renderButton:function(e){var i=this,a=i._getLayoutTemplate("btnDefault"),r=i[e+"Class"],n=i[e+"Title"],o=i[e+"Icon"],l=i[e+"Label"],s=i.isDisabled?" disabled":"",d="button";switch(e){case"remove":if(!i.showRemove)return"";break;case"cancel":if(!i.showCancel)return"";r+=" kv-hidden";break;case"upload":if(!i.showUpload)return"";i.isAjaxUpload&&!i.isDisabled?a=i._getLayoutTemplate("btnLink").replace("{href}",i.uploadUrl):d="submit";break;case"browse":if(!i.showBrowse)return"";a=i._getLayoutTemplate("btnBrowse");break;default:return""}return r+="browse"===e?" btn-file":" fileinput-"+e+" fileinput-"+e+"-button",t.isEmpty(l)||(l=' <span class="'+i.buttonLabelClass+'">'+l+"</span>"),a.setTokens({type:d,css:r,title:n,status:s,icon:o,label:l})},_renderThumbProgress:function(){var e=this;return'<div class="file-thumb-progress kv-hidden">'+e.progressTemplate.setTokens({percent:"0",status:e.msgUploadBegin})+"</div>"},_renderFileFooter:function(e,i,a,r){var n,o=this,l=o.fileActionSettings,s=l.showRemove,d=l.showDrag,c=l.showUpload,p=l.showZoom,u=o._getLayoutTemplate("footer"),f=o._getLayoutTemplate("indicator"),m=r?l.indicatorError:l.indicatorNew,v=r?l.indicatorErrorTitle:l.indicatorNewTitle,g=f.setTokens({indicator:m,indicatorTitle:v});return i=o._getSize(i),n=o.isAjaxUpload?u.setTokens({actions:o._renderFileActions(c,!1,s,p,d,!1,!1,!1),caption:e,size:i,width:a,progress:o._renderThumbProgress(),indicator:g}):u.setTokens({actions:o._renderFileActions(!1,!1,!1,p,d,!1,!1,!1),caption:e,size:i,width:a,progress:"",indicator:g}),n=t.replaceTags(n,o.previewThumbTags)},_renderFileActions:function(e,t,i,a,r,n,o,l,s,d,c){if(!(e||t||i||a||r))return"";var p,u=this,f=o===!1?"":' data-url="'+o+'"',m=l===!1?"":' data-key="'+l+'"',v="",g="",h="",w="",_="",b=u._getLayoutTemplate("actions"),C=u.fileActionSettings,y=u.otherActionButtons.setTokens({dataKey:m,key:l}),x=n?C.removeClass+" disabled":C.removeClass;return i&&(v=u._getLayoutTemplate("actionDelete").setTokens({removeClass:x,removeIcon:C.removeIcon,removeTitle:C.removeTitle,dataUrl:f,dataKey:m,key:l})),e&&(g=u._getLayoutTemplate("actionUpload").setTokens({uploadClass:C.uploadClass,uploadIcon:C.uploadIcon,uploadTitle:C.uploadTitle})),t&&(h=u._getLayoutTemplate("actionDownload").setTokens({downloadClass:C.downloadClass,downloadIcon:C.downloadIcon,downloadTitle:C.downloadTitle,downloadUrl:d||u.initialPreviewDownloadUrl}),h=h.setTokens({filename:c,key:l})),a&&(w=u._getLayoutTemplate("actionZoom").setTokens({zoomClass:C.zoomClass,zoomIcon:C.zoomIcon,zoomTitle:C.zoomTitle})),r&&s&&(p="drag-handle-init "+C.dragClass,_=u._getLayoutTemplate("actionDrag").setTokens({dragClass:p,dragTitle:C.dragTitle,dragIcon:C.dragIcon})),b.setTokens({"delete":v,upload:g,download:h,zoom:w,drag:_,other:y})},_browse:function(e){var t=this;e&&e.isDefaultPrevented()||!t._raise("filebrowse")||(t.isError&&!t.isAjaxUpload&&t.clear(),t.$captionContainer.focus())},_filterDuplicate:function(e,t,i){var a=this,r=a._getFileId(e);r&&i&&i.indexOf(r)>-1||(i||(i=[]),t.push(e),i.push(r))},_change:function(i){var a=this;if(!a.changeTriggered){var r,n,o=a.$element,l=arguments.length>1,s=a.isAjaxUpload,d=[],c=l?arguments[1]:o.get(0).files,p=!s&&t.isEmpty(o.attr("multiple"))?1:a.maxFileCount,u=a.filestack.length,f=t.isEmpty(o.attr("multiple")),m=f&&u>0,v=a._getFileIds(),g=function(t,i,r,n){var o=e.extend(!0,{},a._getOutData({},{},c),{id:r,index:n}),l={id:r,index:n,file:i,files:c};return s?a._showUploadError(t,o):a._showError(t,l)},h=function(e,t){var i=a.msgFilesTooMany.replace("{m}",t).replace("{n}",e);a.isError=g(i,null,null,null),a.$captionContainer.removeClass("icon-visible"),a._setCaption("",!0),a.$container.removeClass("file-input-new file-input-ajax-new")};if(a.reader=null,a._resetUpload(),a._hideFileIcon(),a.dropZoneEnabled&&a.$container.find(".file-drop-zone ."+a.dropZoneTitleClass).remove(),s?e.each(c,function(e,t){a._filterDuplicate(t,d,v)}):(c=i.target&&void 0===i.target.files?i.target.value?[{name:i.target.value.replace(/^.+\\/,"")}]:[]:i.target.files||{},d=c),t.isEmpty(d)||0===d.length)return s||a.clear(),void a._raise("fileselectnone");if(a._resetErrors(),n=d.length,r=a._getFileCount(s?a.getFileStack().length+n:n),p>0&&r>p){if(!a.autoReplace||n>p)return void h(a.autoReplace&&n>p?n:r,p);r>p&&a._resetPreviewThumbs(s)}else!s||m?(a._resetPreviewThumbs(!1),m&&a.clearStack()):!s||0!==u||a.previewCache.count()&&!a.overwriteInitial||a._resetPreviewThumbs(!0);a.isPreviewable?a.readFiles(d):a._updateFileDetails(1)}},_abort:function(t){var i,a=this;return a.ajaxAborted&&"object"==typeof a.ajaxAborted&&void 0!==a.ajaxAborted.message?(i=e.extend(!0,{},a._getOutData(),t),i.abortData=a.ajaxAborted.data||{},i.abortMessage=a.ajaxAborted.message,a._setProgress(101,a.$progress,a.msgCancelled),a._showUploadError(a.ajaxAborted.message,i,"filecustomerror"),a.cancel(),!0):!!a.ajaxAborted},_resetFileStack:function(){var i=this,a=0,r=[],n=[],o=[];i._getThumbs().each(function(){var l=e(this),s=l.attr("data-fileindex"),d=i.filestack[s],c=l.attr("id");"-1"!==s&&-1!==s&&(void 0!==d?(r[a]=d,n[a]=i._getFileName(d),o[a]=i._getFileId(d),l.attr({id:i.previewInitId+"-"+a,"data-fileindex":a}),a++):l.attr({id:"uploaded-"+t.uniqId(),"data-fileindex":"-1"}),i.$preview.find("#zoom-"+c).attr({id:"zoom-"+l.attr("id"),"data-fileindex":l.attr("data-fileindex")}))}),i.filestack=r,i.filenames=n,i.fileids=o},_isFileSelectionValid:function(e){var t=this;return e=e||0,t.required&&!t.getFilesCount()?(t.$errorContainer.html(""),t._showUploadError(t.msgFileRequired),!1):t.minFileCount>0&&t._getFileCount(e)<t.minFileCount?(t._noFilesError({}),!1):!0},clearStack:function(){var e=this;return e.filestack=[],e.filenames=[],e.fileids=[],e.$element},updateStack:function(e,t){var i=this;return i.filestack[e]=t,i.filenames[e]=i._getFileName(t),i.fileids[e]=t&&i._getFileId(t)||null,i.$element},addToStack:function(e){var t=this;return t.filestack.push(e),t.filenames.push(t._getFileName(e)),t.fileids.push(t._getFileId(e)),t.$element},getFileStack:function(e){var t=this;return t.filestack.filter(function(t){return e?void 0!==t:void 0!==t&&null!==t})},getFilesCount:function(){var e=this,t=e.isAjaxUpload?e.getFileStack().length:e._inputFileCount();return e._getFileCount(t)},readFiles:function(i){this.reader=new FileReader;var a,r=this,n=r.$element,o=r.$preview,l=r.reader,s=r.$previewContainer,d=r.$previewStatus,c=r.msgLoading,p=r.msgProgress,u=r.previewInitId,f=i.length,m=r.fileTypeSettings,v=r.filestack.length,g=r.allowedFileTypes,h=g?g.length:0,w=r.allowedFileExtensions,_=t.isEmpty(w)?"":w.join(", "),b=r.maxFilePreviewSize&&parseFloat(r.maxFilePreviewSize),C=o.length&&(!b||isNaN(b)),y=function(t,n,o,l){var s,d=e.extend(!0,{},r._getOutData({},{},i),{id:o,index:l}),c={id:o,index:l,file:n,files:i};r._previewDefault(n,o,!0),r.isAjaxUpload?(r.addToStack(void 0),setTimeout(function(){a(l+1)},100)):f=0,r._initFileActions(),s=e("#"+o),s.find(".kv-file-upload").hide(),r.removeFromPreviewOnError&&s.remove(),r.isError=r.isAjaxUpload?r._showUploadError(t,d):r._showError(t,c),r._updateFileDetails(f)};r.loadedImages=[],r.totalImagesCount=0,e.each(i,function(e,t){var i=r.fileTypeSettings.image;i&&i(t.type)&&r.totalImagesCount++}),a=function(x){if(t.isEmpty(n.attr("multiple"))&&(f=1),x>=f)return r.isAjaxUpload&&r.filestack.length>0?r._raise("filebatchselected",[r.getFileStack()]):r._raise("filebatchselected",[i]),s.removeClass("file-thumb-loading"),void d.html("");var T,E,S,k,F,P,I,A,D,z,$,j,U=v+x,R=u+"-"+U,B=i[x],O=m.text,L=m.image,M=m.html,Z=B&&B.name?r.slug(B.name):"",N=(B&&B.size||0)/1e3,H="",q=t.createObjectURL(B),W=0,V="",K=0,Y=function(){var e=p.setTokens({index:x+1,files:f,percent:50,name:Z});setTimeout(function(){d.html(e),r._updateFileDetails(f),a(x+1)},100),r._raise("fileloaded",[B,R,x,l])};if(B){if(h>0)for(E=0;h>E;E++)P=g[E],I=r.msgFileTypes[P]||P,V+=0===E?I:", "+I;if(Z===!1)return void a(x+1);if(0===Z.length)return S=r.msgInvalidFileName.replace("{name}",t.htmlEncode(B.name,"[unknown]")),void y(S,B,R,x);if(t.isEmpty(w)||(H=new RegExp("\\.("+w.join("|")+")$","i")),T=N.toFixed(2),r.maxFileSize>0&&N>r.maxFileSize)return S=r.msgSizeTooLarge.setTokens({name:Z,size:T,maxSize:r.maxFileSize}),void y(S,B,R,x);if(null!==r.minFileSize&&N<=t.getNum(r.minFileSize))return S=r.msgSizeTooSmall.setTokens({name:Z,size:T,minSize:r.minFileSize}),void y(S,B,R,x);if(!t.isEmpty(g)&&t.isArray(g)){for(E=0;E<g.length;E+=1)k=g[E],A=m[k],W+=A&&"function"==typeof A&&A(B.type,B.name)?1:0;if(0===W)return S=r.msgInvalidFileType.setTokens({name:Z,types:V}),void y(S,B,R,x)}if(0===W&&!t.isEmpty(w)&&t.isArray(w)&&!t.isEmpty(H)&&(F=t.compare(Z,H),W+=t.isEmpty(F)?0:F.length,0===W))return S=r.msgInvalidFileExtension.setTokens({name:Z,extensions:_}),void y(S,B,R,x);if(!r.showPreview)return r.isAjaxUpload&&r.addToStack(B),setTimeout(function(){a(x+1),r._updateFileDetails(f)},100),void r._raise("fileloaded",[B,R,x,l]);if(!C&&N>b)return r.addToStack(B),s.addClass("file-thumb-loading"),r._previewDefault(B,R),r._initFileActions(),r._updateFileDetails(f),void a(x+1);o.length&&void 0!==FileReader?(D=O(B.type,Z),z=M(B.type,Z),$=L(B.type,Z),d.html(c.replace("{index}",x+1).replace("{files}",f)),s.addClass("file-thumb-loading"),l.onerror=function(e){r._errorHandler(e,Z)},l.onload=function(i){var a,n,o,s,d,c,p=[],u=function(e){var t=new FileReader;t.onerror=function(e){r._errorHandler(e,Z)},t.onload=function(e){r._previewFile(x,B,e,R,q,n),r._initFileActions(),Y()},e?t.readAsText(B,r.textEncoding):t.readAsDataURL(B)};if(n={name:Z,type:B.type},e.each(m,function(e,t){"object"!==e&&"other"!==e&&"function"==typeof t&&t(B.type,Z)&&K++}),0===K){for(o=new Uint8Array(i.target.result),E=0;E<o.length;E++)s=o[E].toString(16),p.push(s);if(a=p.join("").toLowerCase().substring(0,8),c=t.getMimeType(a,"",""),t.isEmpty(c)&&(d=t.arrayBuffer2String(l.result),c=t.isSvg(d)?"image/svg+xml":t.getMimeType(a,d,B.type)),n={name:Z,type:c},D=O(c,""),z=M(c,""),$=L(c,""),j=D||z,j||$)return void u(j)}r._previewFile(x,B,i,R,q,n),r._initFileActions(),Y()},l.onprogress=function(e){if(e.lengthComputable){var t=e.loaded/e.total*100,i=Math.ceil(t);S=p.setTokens({index:x+1,files:f,percent:i,name:Z}),setTimeout(function(){d.html(S)},100)}},D||z?l.readAsText(B,r.textEncoding):$?l.readAsDataURL(B):l.readAsArrayBuffer(B)):(r._previewDefault(B,R),setTimeout(function(){a(x+1),r._updateFileDetails(f)},100),r._raise("fileloaded",[B,R,x,l])),r.addToStack(B)}},a(0),r._updateFileDetails(f,!1)},lock:function(){var e=this;return e._resetErrors(),e.disable(),e.showRemove&&e.$container.find(".fileinput-remove").hide(),e.showCancel&&e.$container.find(".fileinput-cancel").show(),e._raise("filelock",[e.filestack,e._getExtraData()]),e.$element},unlock:function(e){var t=this;return void 0===e&&(e=!0),t.enable(),t.showCancel&&t.$container.find(".fileinput-cancel").hide(),t.showRemove&&t.$container.find(".fileinput-remove").show(),e&&t._resetFileStack(),t._raise("fileunlock",[t.filestack,t._getExtraData()]),t.$element},cancel:function(){var t,i=this,a=i.ajaxRequests,r=a.length;if(r>0)for(t=0;r>t;t+=1)i.cancelling=!0,a[t].abort();return i._setProgressCancelled(),i._getThumbs().each(function(){var t=e(this),a=t.attr("data-fileindex");t.removeClass("file-uploading"),void 0!==i.filestack[a]&&(t.find(".kv-file-upload").removeClass("disabled").removeAttr("disabled"),t.find(".kv-file-remove").removeClass("disabled").removeAttr("disabled")),i.unlock()}),i.$element},clear:function(){var i,a=this;if(a._raise("fileclear"))return a.$btnUpload.removeAttr("disabled"),a._getThumbs().find("video,audio,img").each(function(){t.cleanMemory(e(this))}),a._clearFileInput(),a._resetUpload(),a.clearStack(),a._resetErrors(!0),a._hasInitialPreview()?(a._showFileIcon(),a._resetPreview(),a._initPreviewActions(),a.$container.removeClass("file-input-new")):(a._getThumbs().each(function(){a._clearObjects(e(this))}),a.isAjaxUpload&&(a.previewCache.data={}),a.$preview.html(""),i=!a.overwriteInitial&&a.initialCaption.length>0?a.initialCaption:"",a.$caption.attr("title","").val(i),t.addCss(a.$container,"file-input-new"),a._validateDefaultPreview()),0===a.$container.find(t.FRAMES).length&&(a._initCaption()||a.$captionContainer.removeClass("icon-visible")),a._hideFileIcon(),a._raise("filecleared"),a.$captionContainer.focus(),a._setFileDropZoneTitle(),a.$element},reset:function(){var e=this;if(e._raise("filereset"))return e._resetPreview(),e.$container.find(".fileinput-filename").text(""),t.addCss(e.$container,"file-input-new"),(e.getFrames().length||e.dropZoneEnabled)&&e.$container.removeClass("file-input-new"),e.clearStack(),e.formdata={},e._setFileDropZoneTitle(),e.$element},disable:function(){var e=this;return e.isDisabled=!0,e._raise("filedisabled"),e.$element.attr("disabled","disabled"),e.$container.find(".kv-fileinput-caption").addClass("file-caption-disabled"),e.$container.find(".fileinput-remove, .fileinput-upload, .file-preview-frame button").attr("disabled",!0),t.addCss(e.$container.find(".btn-file"),"disabled"),e._initDragDrop(),e.$element},enable:function(){var e=this;return e.isDisabled=!1,e._raise("fileenabled"),e.$element.removeAttr("disabled"),e.$container.find(".kv-fileinput-caption").removeClass("file-caption-disabled"),e.$container.find(".fileinput-remove, .fileinput-upload, .file-preview-frame button").removeAttr("disabled"),e.$container.find(".btn-file").removeClass("disabled"),e._initDragDrop(),e.$element},upload:function(){var i,a,r,n=this,o=n.getFileStack().length,l=!e.isEmptyObject(n._getExtraData());if(n.isAjaxUpload&&!n.isDisabled&&n._isFileSelectionValid(o)){if(n._resetUpload(),0===o&&!l)return void n._showUploadError(n.msgUploadEmpty);if(n.$progress.show(),n.uploadCount=0,n.uploadStatus={},n.uploadLog=[],n.lock(),n._setProgress(2),0===o&&l)return void n._uploadExtraOnly();if(r=n.filestack.length,n.hasInitData=!1,!n.uploadAsync)return n._uploadBatch(),n.$element;for(a=n._getOutData(),n._raise("filebatchpreupload",[a]),n.fileBatchCompleted=!1,n.uploadCache={content:[],config:[],tags:[],append:!0},n.uploadAsyncCount=n.getFileStack().length,i=0;r>i;i++)n.uploadCache.content[i]=null,n.uploadCache.config[i]=null,n.uploadCache.tags[i]=null;for(n.$preview.find(".file-preview-initial").removeClass(t.SORT_CSS),n._initSortable(),n.cacheInitialPreview=n.getPreview(),i=0;r>i;i++)n.filestack[i]&&n._uploadSingle(i,!0)}},destroy:function(){var t=this,i=t.$form,a=t.$container,r=t.$element,n=t.namespace;return e(document).off(n),e(window).off(n),i&&i.length&&i.off(n),t.isAjaxUpload&&t._clearFileInput(),t._cleanup(),t._initPreviewCache(),r.insertBefore(a).off(n).removeData(),a.off().remove(),r},refresh:function(i){var a=this,r=a.$element;return i="object"!=typeof i||t.isEmpty(i)?a.options:e.extend(!0,{},a.options,i),a._init(i,!0),a._listen(),r},zoom:function(e){var i=this,a=i._getFrame(e),r=i.$modal;a&&(t.initModal(r),r.html(i._getModalContent()),i._setZoomContent(a),r.modal("show"),i._initZoomButtons())},getExif:function(e){var t=this,i=t._getFrame(e);return i&&i.data("exif")||null},getFrames:function(i){var a,r=this;return i=i||"",a=r.$preview.find(t.FRAMES+i),r.reversePreviewOrder&&(a=e(a.get().reverse())),a},getPreview:function(){var e=this;return{content:e.initialPreview,config:e.initialPreviewConfig,tags:e.initialPreviewThumbTags}}},e.fn.fileinput=function(a){if(t.hasFileAPISupport()||t.isIE(9)){var r=Array.apply(null,arguments),n=[];switch(r.shift(),this.each(function(){var o,l=e(this),s=l.data("fileinput"),d="object"==typeof a&&a,c=d.theme||l.data("theme"),p={},u={},f=d.language||l.data("language")||e.fn.fileinput.defaults.language||"en";s||(c&&(u=e.fn.fileinputThemes[c]||{}),"en"===f||t.isEmpty(e.fn.fileinputLocales[f])||(p=e.fn.fileinputLocales[f]||{}),o=e.extend(!0,{},e.fn.fileinput.defaults,u,e.fn.fileinputLocales.en,p,d,l.data()),s=new i(this,o),l.data("fileinput",s)),"string"==typeof a&&n.push(s[a].apply(s,r))}),n.length){case 0:return this;case 1:return n[0];default:return n}}},e.fn.fileinput.defaults={language:"en",showCaption:!0,showBrowse:!0,showPreview:!0,showRemove:!0,showUpload:!0,showCancel:!0,showClose:!0,showUploadedThumbs:!0,browseOnZoneClick:!1,autoReplace:!1,autoOrientImage:!1,required:!1,rtl:!1,hideThumbnailContent:!1,encodeUrl:!0,generateFileId:null,previewClass:"",captionClass:"",frameClass:"krajee-default",mainClass:"file-caption-main",mainTemplate:null,purifyHtml:!0,fileSizeGetter:null,initialCaption:"",initialPreview:[],initialPreviewDelimiter:"*$$*",initialPreviewAsData:!1,initialPreviewFileType:"image",initialPreviewConfig:[],initialPreviewThumbTags:[],previewThumbTags:{},initialPreviewShowDelete:!0,initialPreviewDownloadUrl:"",removeFromPreviewOnError:!1,deleteUrl:"",deleteExtraData:{},overwriteInitial:!0,previewZoomButtonIcons:{prev:'<i class="glyphicon glyphicon-triangle-left"></i>',next:'<i class="glyphicon glyphicon-triangle-right"></i>',toggleheader:'<i class="glyphicon glyphicon-resize-vertical"></i>',fullscreen:'<i class="glyphicon glyphicon-fullscreen"></i>',borderless:'<i class="glyphicon glyphicon-resize-full"></i>',close:'<i class="glyphicon glyphicon-remove"></i>'},previewZoomButtonClasses:{prev:"btn btn-navigate",next:"btn btn-navigate",toggleheader:"btn btn-sm btn-kv btn-default btn-outline-secondary",fullscreen:"btn btn-sm btn-kv btn-default btn-outline-secondary",borderless:"btn btn-sm btn-kv btn-default btn-outline-secondary",close:"btn btn-sm btn-kv btn-default btn-outline-secondary"},previewTemplates:{},previewContentTemplates:{},preferIconicPreview:!1,preferIconicZoomPreview:!1,allowedPreviewTypes:void 0,allowedPreviewMimeTypes:null,allowedFileTypes:null,allowedFileExtensions:null,defaultPreviewContent:null,customLayoutTags:{},customPreviewTags:{},previewFileIcon:'<i class="glyphicon glyphicon-file"></i>',previewFileIconClass:"file-other-icon",previewFileIconSettings:{},previewFileExtSettings:{},buttonLabelClass:"hidden-xs",browseIcon:'<i class="glyphicon glyphicon-folder-open"></i> ',browseClass:"btn btn-primary",removeIcon:'<i class="glyphicon glyphicon-trash"></i>',removeClass:"btn btn-default btn-secondary",cancelIcon:'<i class="glyphicon glyphicon-ban-circle"></i>',cancelClass:"btn btn-default btn-secondary",uploadIcon:'<i class="glyphicon glyphicon-upload"></i>',uploadClass:"btn btn-default btn-secondary",uploadUrl:null,uploadUrlThumb:null,uploadAsync:!0,uploadExtraData:{},zoomModalHeight:480,minImageWidth:null,minImageHeight:null,maxImageWidth:null,maxImageHeight:null,resizeImage:!1,resizePreference:"width",resizeQuality:.92,resizeDefaultImageType:"image/jpeg",resizeIfSizeMoreThan:0,minFileSize:0,maxFileSize:0,maxFilePreviewSize:25600,minFileCount:0,maxFileCount:0,validateInitialCount:!1,msgValidationErrorClass:"text-danger",msgValidationErrorIcon:'<i class="glyphicon glyphicon-exclamation-sign"></i> ',msgErrorClass:"file-error-message",progressThumbClass:"progress-bar bg-success progress-bar-success progress-bar-striped active",progressClass:"progress-bar bg-success progress-bar-success progress-bar-striped active",progressCompleteClass:"progress-bar bg-success progress-bar-success",progressErrorClass:"progress-bar bg-danger progress-bar-danger",progressUploadThreshold:99,previewFileType:"image",elCaptionContainer:null,elCaptionText:null,elPreviewContainer:null,elPreviewImage:null,elPreviewStatus:null,elErrorContainer:null,errorCloseButton:t.closeButton("kv-error-close"),slugCallback:null,dropZoneEnabled:!0,dropZoneTitleClass:"file-drop-zone-title",fileActionSettings:{},otherActionButtons:"",textEncoding:"UTF-8",ajaxSettings:{},ajaxDeleteSettings:{},showAjaxErrorDetails:!0,mergeAjaxCallbacks:!1,mergeAjaxDeleteCallbacks:!1,retryErrorUploads:!0,reversePreviewOrder:!1},e.fn.fileinputLocales.en={fileSingle:"file",filePlural:"files",browseLabel:"Browse …",removeLabel:"Remove",removeTitle:"Clear selected files",cancelLabel:"Cancel",cancelTitle:"Abort ongoing upload",uploadLabel:"Upload",uploadTitle:"Upload selected files",msgNo:"No",msgNoFilesSelected:"No files selected",msgCancelled:"Cancelled",msgPlaceholder:"Select {files}...",msgZoomModalHeading:"Detailed Preview",msgFileRequired:"You must select a file to upload.",msgSizeTooSmall:'File "{name}" (<b>{size} KB</b>) is too small and must be larger than <b>{minSize} KB</b>.',msgSizeTooLarge:'File "{name}" (<b>{size} KB</b>) exceeds maximum allowed upload size of <b>{maxSize} KB</b>.',msgFilesTooLess:"You must select at least <b>{n}</b> {files} to upload.",msgFilesTooMany:"Number of files selected for upload <b>({n})</b> exceeds maximum allowed limit of <b>{m}</b>.",msgFileNotFound:'File "{name}" not found!',msgFileSecured:'Security restrictions prevent reading the file "{name}".',msgFileNotReadable:'File "{name}" is not readable.',msgFilePreviewAborted:'File preview aborted for "{name}".',msgFilePreviewError:'An error occurred while reading the file "{name}".',msgInvalidFileName:'Invalid or unsupported characters in file name "{name}".',msgInvalidFileType:'Invalid type for file "{name}". Only "{types}" files are supported.',msgInvalidFileExtension:'Invalid extension for file "{name}". Only "{extensions}" files are supported.',msgFileTypes:{image:"image",html:"HTML",text:"text",video:"video",audio:"audio",flash:"flash",pdf:"PDF",object:"object"},msgUploadAborted:"The file upload was aborted",msgUploadThreshold:"Processing...",msgUploadBegin:"Initializing...",msgUploadEnd:"Done",msgUploadEmpty:"No valid data available for upload.",msgUploadError:"Error",msgValidationError:"Validation Error",msgLoading:"Loading file {index} of {files} …",msgProgress:"Loading file {index} of {files} - {name} - {percent}% completed.",msgSelected:"{n} {files} selected",msgFoldersNotAllowed:"Drag & drop files only! {n} folder(s) dropped were skipped.",msgImageWidthSmall:'Width of image file "{name}" must be at least {size} px.',msgImageHeightSmall:'Height of image file "{name}" must be at least {size} px.',msgImageWidthLarge:'Width of image file "{name}" cannot exceed {size} px.',msgImageHeightLarge:'Height of image file "{name}" cannot exceed {size} px.',msgImageResizeError:"Could not get the image dimensions to resize.",msgImageResizeException:"Error while resizing the image.<pre>{errors}</pre>",msgAjaxError:"Something went wrong with the {operation} operation. Please try again later!",msgAjaxProgressError:"{operation} failed",ajaxOperations:{deleteThumb:"file delete",uploadThumb:"file upload",uploadBatch:"batch file upload",uploadExtra:"form data upload"},dropZoneTitle:"Drag & drop files here …",dropZoneClickTitle:"<br>(or click to select {files})",previewZoomButtonTitles:{prev:"View previous file",next:"View next file",toggleheader:"Toggle header",fullscreen:"Toggle full screen",borderless:"Toggle borderless mode",close:"Close detailed preview"},usePdfRenderer:function(){var e=!!window.MSInputMethodContext&&!!document.documentMode;return!!navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/i)||e},pdfRendererUrl:"",pdfRendererTemplate:'<iframe class="kv-preview-data file-preview-pdf" src="{renderer}?file={data}" {style}></iframe>'},e.fn.fileinput.Constructor=i,e(document).ready(function(){ var t=e("input.file[type=file]");t.length&&t.fileinput()})}); +/* flatpickr v4.6.13,, @license MIT */ +!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).flatpickr=n()}(this,(function(){"use strict";var e=function(){return(e=Object.assign||function(e){for(var n,t=1,a=arguments.length;t<a;t++)for(var i in n=arguments[t])Object.prototype.hasOwnProperty.call(n,i)&&(e[i]=n[i]);return e}).apply(this,arguments)};function n(){for(var e=0,n=0,t=arguments.length;n<t;n++)e+=arguments[n].length;var a=Array(e),i=0;for(n=0;n<t;n++)for(var o=arguments[n],r=0,l=o.length;r<l;r++,i++)a[i]=o[r];return a}var t=["onChange","onClose","onDayCreate","onDestroy","onKeyDown","onMonthChange","onOpen","onParseConfig","onReady","onValueUpdate","onYearChange","onPreCalendarPosition"],a={_disable:[],allowInput:!1,allowInvalidPreload:!1,altFormat:"F j, Y",altInput:!1,altInputClass:"form-control input",animate:"object"==typeof window&&-1===window.navigator.userAgent.indexOf("MSIE"),ariaDateFormat:"F j, Y",autoFillDefaultTime:!0,clickOpens:!0,closeOnSelect:!0,conjunction:", ",dateFormat:"Y-m-d",defaultHour:12,defaultMinute:0,defaultSeconds:0,disable:[],disableMobile:!1,enableSeconds:!1,enableTime:!1,errorHandler:function(e){return"undefined"!=typeof console&&console.warn(e)},getWeek:function(e){var n=new Date(e.getTime());n.setHours(0,0,0,0),n.setDate(n.getDate()+3-(n.getDay()+6)%7);var t=new Date(n.getFullYear(),0,4);return 1+Math.round(((n.getTime()-t.getTime())/864e5-3+(t.getDay()+6)%7)/7)},hourIncrement:1,ignoredFocusElements:[],inline:!1,locale:"default",minuteIncrement:5,mode:"single",monthSelectorType:"dropdown",nextArrow:"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M13.207 8.472l-7.854 7.854-0.707-0.707 7.146-7.146-7.146-7.148 0.707-0.707 7.854 7.854z' /></svg>",noCalendar:!1,now:new Date,onChange:[],onClose:[],onDayCreate:[],onDestroy:[],onKeyDown:[],onMonthChange:[],onOpen:[],onParseConfig:[],onReady:[],onValueUpdate:[],onYearChange:[],onPreCalendarPosition:[],plugins:[],position:"auto",positionElement:void 0,prevArrow:"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M5.207 8.471l7.146 7.147-0.707 0.707-7.853-7.854 7.854-7.853 0.707 0.707-7.147 7.146z' /></svg>",shorthandCurrentMonth:!1,showMonths:1,static:!1,time_24hr:!1,weekNumbers:!1,wrap:!1},i={weekdays:{shorthand:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],longhand:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},months:{shorthand:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],longhand:["January","February","March","April","May","June","July","August","September","October","November","December"]},daysInMonth:[31,28,31,30,31,30,31,31,30,31,30,31],firstDayOfWeek:0,ordinal:function(e){var n=e%100;if(n>3&&n<21)return"th";switch(n%10){case 1:return"st";case 2:return"nd";case 3:return"rd";default:return"th"}},rangeSeparator:" to ",weekAbbreviation:"Wk",scrollTitle:"Scroll to increment",toggleTitle:"Click to toggle",amPM:["AM","PM"],yearAriaLabel:"Year",monthAriaLabel:"Month",hourAriaLabel:"Hour",minuteAriaLabel:"Minute",time_24hr:!1},o=function(e,n){return void 0===n&&(n=2),("000"+e).slice(-1*n)},r=function(e){return!0===e?1:0};function l(e,n){var t;return function(){var a=this,i=arguments;clearTimeout(t),t=setTimeout((function(){return e.apply(a,i)}),n)}}var c=function(e){return e instanceof Array?e:[e]};function s(e,n,t){if(!0===t)return e.classList.add(n);e.classList.remove(n)}function d(e,n,t){var a=window.document.createElement(e);return n=n||"",t=t||"",a.className=n,void 0!==t&&(a.textContent=t),a}function u(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function f(e,n){return n(e)?e:e.parentNode?f(e.parentNode,n):void 0}function m(e,n){var t=d("div","numInputWrapper"),a=d("input","numInput "+e),i=d("span","arrowUp"),o=d("span","arrowDown");if(-1===navigator.userAgent.indexOf("MSIE 9.0")?a.type="number":(a.type="text",a.pattern="\\d*"),void 0!==n)for(var r in n)a.setAttribute(r,n[r]);return t.appendChild(a),t.appendChild(i),t.appendChild(o),t}function g(e){try{return"function"==typeof e.composedPath?e.composedPath()[0]:e.target}catch(n){return e.target}}var p=function(){},h=function(e,n,t){return t.months[n?"shorthand":"longhand"][e]},v={D:p,F:function(e,n,t){e.setMonth(t.months.longhand.indexOf(n))},G:function(e,n){e.setHours((e.getHours()>=12?12:0)+parseFloat(n))},H:function(e,n){e.setHours(parseFloat(n))},J:function(e,n){e.setDate(parseFloat(n))},K:function(e,n,t){e.setHours(e.getHours()%12+12*r(new RegExp(t.amPM[1],"i").test(n)))},M:function(e,n,t){e.setMonth(t.months.shorthand.indexOf(n))},S:function(e,n){e.setSeconds(parseFloat(n))},U:function(e,n){return new Date(1e3*parseFloat(n))},W:function(e,n,t){var a=parseInt(n),i=new Date(e.getFullYear(),0,2+7*(a-1),0,0,0,0);return i.setDate(i.getDate()-i.getDay()+t.firstDayOfWeek),i},Y:function(e,n){e.setFullYear(parseFloat(n))},Z:function(e,n){return new Date(n)},d:function(e,n){e.setDate(parseFloat(n))},h:function(e,n){e.setHours((e.getHours()>=12?12:0)+parseFloat(n))},i:function(e,n){e.setMinutes(parseFloat(n))},j:function(e,n){e.setDate(parseFloat(n))},l:p,m:function(e,n){e.setMonth(parseFloat(n)-1)},n:function(e,n){e.setMonth(parseFloat(n)-1)},s:function(e,n){e.setSeconds(parseFloat(n))},u:function(e,n){return new Date(parseFloat(n))},w:p,y:function(e,n){e.setFullYear(2e3+parseFloat(n))}},D={D:"",F:"",G:"(\\d\\d|\\d)",H:"(\\d\\d|\\d)",J:"(\\d\\d|\\d)\\w+",K:"",M:"",S:"(\\d\\d|\\d)",U:"(.+)",W:"(\\d\\d|\\d)",Y:"(\\d{4})",Z:"(.+)",d:"(\\d\\d|\\d)",h:"(\\d\\d|\\d)",i:"(\\d\\d|\\d)",j:"(\\d\\d|\\d)",l:"",m:"(\\d\\d|\\d)",n:"(\\d\\d|\\d)",s:"(\\d\\d|\\d)",u:"(.+)",w:"(\\d\\d|\\d)",y:"(\\d{2})"},w={Z:function(e){return e.toISOString()},D:function(e,n,t){return n.weekdays.shorthand[w.w(e,n,t)]},F:function(e,n,t){return h(w.n(e,n,t)-1,!1,n)},G:function(e,n,t){return o(w.h(e,n,t))},H:function(e){return o(e.getHours())},J:function(e,n){return void 0!==n.ordinal?e.getDate()+n.ordinal(e.getDate()):e.getDate()},K:function(e,n){return n.amPM[r(e.getHours()>11)]},M:function(e,n){return h(e.getMonth(),!0,n)},S:function(e){return o(e.getSeconds())},U:function(e){return e.getTime()/1e3},W:function(e,n,t){return t.getWeek(e)},Y:function(e){return o(e.getFullYear(),4)},d:function(e){return o(e.getDate())},h:function(e){return e.getHours()%12?e.getHours()%12:12},i:function(e){return o(e.getMinutes())},j:function(e){return e.getDate()},l:function(e,n){return n.weekdays.longhand[e.getDay()]},m:function(e){return o(e.getMonth()+1)},n:function(e){return e.getMonth()+1},s:function(e){return e.getSeconds()},u:function(e){return e.getTime()},w:function(e){return e.getDay()},y:function(e){return String(e.getFullYear()).substring(2)}},b=function(e){var n=e.config,t=void 0===n?a:n,o=e.l10n,r=void 0===o?i:o,l=e.isMobile,c=void 0!==l&&l;return function(e,n,a){var i=a||r;return void 0===t.formatDate||c?n.split("").map((function(n,a,o){return w[n]&&"\\"!==o[a-1]?w[n](e,i,t):"\\"!==n?n:""})).join(""):t.formatDate(e,n,i)}},C=function(e){var n=e.config,t=void 0===n?a:n,o=e.l10n,r=void 0===o?i:o;return function(e,n,i,o){if(0===e||e){var l,c=o||r,s=e;if(e instanceof Date)l=new Date(e.getTime());else if("string"!=typeof e&&void 0!==e.toFixed)l=new Date(e);else if("string"==typeof e){var d=n||(t||a).dateFormat,u=String(e).trim();if("today"===u)l=new Date,i=!0;else if(t&&t.parseDate)l=t.parseDate(e,d);else if(/Z$/.test(u)||/GMT$/.test(u))l=new Date(e);else{for(var f=void 0,m=[],g=0,p=0,h="";g<d.length;g++){var w=d[g],b="\\"===w,C="\\"===d[g-1]||b;if(D[w]&&!C){h+=D[w];var M=new RegExp(h).exec(e);M&&(f=!0)&&m["Y"!==w?"push":"unshift"]({fn:v[w],val:M[++p]})}else b||(h+=".")}l=t&&t.noCalendar?new Date((new Date).setHours(0,0,0,0)):new Date((new Date).getFullYear(),0,1,0,0,0,0),m.forEach((function(e){var n=e.fn,t=e.val;return l=n(l,t,c)||l})),l=f?l:void 0}}if(l instanceof Date&&!isNaN(l.getTime()))return!0===i&&l.setHours(0,0,0,0),l;t.errorHandler(new Error("Invalid date provided: "+s))}}};function M(e,n,t){return void 0===t&&(t=!0),!1!==t?new Date(e.getTime()).setHours(0,0,0,0)-new Date(n.getTime()).setHours(0,0,0,0):e.getTime()-n.getTime()}var y=function(e,n,t){return 3600*e+60*n+t},x=864e5;function E(e){var n=e.defaultHour,t=e.defaultMinute,a=e.defaultSeconds;if(void 0!==e.minDate){var i=e.minDate.getHours(),o=e.minDate.getMinutes(),r=e.minDate.getSeconds();n<i&&(n=i),n===i&&t<o&&(t=o),n===i&&t===o&&a<r&&(a=e.minDate.getSeconds())}if(void 0!==e.maxDate){var l=e.maxDate.getHours(),c=e.maxDate.getMinutes();(n=Math.min(n,l))===l&&(t=Math.min(c,t)),n===l&&t===c&&(a=e.maxDate.getSeconds())}return{hours:n,minutes:t,seconds:a}}"function"!=typeof Object.assign&&(Object.assign=function(e){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];if(!e)throw TypeError("Cannot convert undefined or null to object");for(var a=function(n){n&&Object.keys(n).forEach((function(t){return e[t]=n[t]}))},i=0,o=n;i<o.length;i++){var r=o[i];a(r)}return e});function k(p,v){var w={config:e(e({},a),I.defaultConfig),l10n:i};function k(){var e;return(null===(e=w.calendarContainer)||void 0===e?void 0:e.getRootNode()).activeElement||document.activeElement}function T(e){return e.bind(w)}function S(){var e=w.config;!1===e.weekNumbers&&1===e.showMonths||!0!==e.noCalendar&&window.requestAnimationFrame((function(){if(void 0!==w.calendarContainer&&(w.calendarContainer.style.visibility="hidden",w.calendarContainer.style.display="block"),void 0!==w.daysContainer){var n=(w.days.offsetWidth+1)*e.showMonths;w.daysContainer.style.width=n+"px",w.calendarContainer.style.width=n+(void 0!==w.weekWrapper?w.weekWrapper.offsetWidth:0)+"px",w.calendarContainer.style.removeProperty("visibility"),w.calendarContainer.style.removeProperty("display")}}))}function _(e){if(0===w.selectedDates.length){var n=void 0===w.config.minDate||M(new Date,w.config.minDate)>=0?new Date:new Date(w.config.minDate.getTime()),t=E(w.config);n.setHours(t.hours,t.minutes,t.seconds,n.getMilliseconds()),w.selectedDates=[n],w.latestSelectedDateObj=n}void 0!==e&&"blur"!==e.type&&function(e){e.preventDefault();var n="keydown"===e.type,t=g(e),a=t;void 0!==w.amPM&&t===w.amPM&&(w.amPM.textContent=w.l10n.amPM[r(w.amPM.textContent===w.l10n.amPM[0])]);var i=parseFloat(a.getAttribute("min")),l=parseFloat(a.getAttribute("max")),c=parseFloat(a.getAttribute("step")),s=parseInt(a.value,10),d=e.delta||(n?38===e.which?1:-1:0),u=s+c*d;if(void 0!==a.value&&2===a.value.length){var f=a===w.hourElement,m=a===w.minuteElement;u<i?(u=l+u+r(!f)+(r(f)&&r(!w.amPM)),m&&L(void 0,-1,w.hourElement)):u>l&&(u=a===w.hourElement?u-l-r(!w.amPM):i,m&&L(void 0,1,w.hourElement)),w.amPM&&f&&(1===c?u+s===23:Math.abs(u-s)>c)&&(w.amPM.textContent=w.l10n.amPM[r(w.amPM.textContent===w.l10n.amPM[0])]),a.value=o(u)}}(e);var a=w._input.value;O(),ye(),w._input.value!==a&&w._debouncedChange()}function O(){if(void 0!==w.hourElement&&void 0!==w.minuteElement){var e,n,t=(parseInt(w.hourElement.value.slice(-2),10)||0)%24,a=(parseInt(w.minuteElement.value,10)||0)%60,i=void 0!==w.secondElement?(parseInt(w.secondElement.value,10)||0)%60:0;void 0!==w.amPM&&(e=t,n=w.amPM.textContent,t=e%12+12*r(n===w.l10n.amPM[1]));var o=void 0!==w.config.minTime||w.config.minDate&&w.minDateHasTime&&w.latestSelectedDateObj&&0===M(w.latestSelectedDateObj,w.config.minDate,!0),l=void 0!==w.config.maxTime||w.config.maxDate&&w.maxDateHasTime&&w.latestSelectedDateObj&&0===M(w.latestSelectedDateObj,w.config.maxDate,!0);if(void 0!==w.config.maxTime&&void 0!==w.config.minTime&&w.config.minTime>w.config.maxTime){var c=y(w.config.minTime.getHours(),w.config.minTime.getMinutes(),w.config.minTime.getSeconds()),s=y(w.config.maxTime.getHours(),w.config.maxTime.getMinutes(),w.config.maxTime.getSeconds()),d=y(t,a,i);if(d>s&&d<c){var u=function(e){var n=Math.floor(e/3600),t=(e-3600*n)/60;return[n,t,e-3600*n-60*t]}(c);t=u[0],a=u[1],i=u[2]}}else{if(l){var f=void 0!==w.config.maxTime?w.config.maxTime:w.config.maxDate;(t=Math.min(t,f.getHours()))===f.getHours()&&(a=Math.min(a,f.getMinutes())),a===f.getMinutes()&&(i=Math.min(i,f.getSeconds()))}if(o){var m=void 0!==w.config.minTime?w.config.minTime:w.config.minDate;(t=Math.max(t,m.getHours()))===m.getHours()&&a<m.getMinutes()&&(a=m.getMinutes()),a===m.getMinutes()&&(i=Math.max(i,m.getSeconds()))}}A(t,a,i)}}function F(e){var n=e||w.latestSelectedDateObj;n&&n instanceof Date&&A(n.getHours(),n.getMinutes(),n.getSeconds())}function A(e,n,t){void 0!==w.latestSelectedDateObj&&w.latestSelectedDateObj.setHours(e%24,n,t||0,0),w.hourElement&&w.minuteElement&&!w.isMobile&&(w.hourElement.value=o(w.config.time_24hr?e:(12+e)%12+12*r(e%12==0)),w.minuteElement.value=o(n),void 0!==w.amPM&&(w.amPM.textContent=w.l10n.amPM[r(e>=12)]),void 0!==w.secondElement&&(w.secondElement.value=o(t)))}function N(e){var n=g(e),t=parseInt(n.value)+(e.delta||0);(t/1e3>1||"Enter"===e.key&&!/[^\d]/.test(t.toString()))&&ee(t)}function P(e,n,t,a){return n instanceof Array?n.forEach((function(n){return P(e,n,t,a)})):e instanceof Array?e.forEach((function(e){return P(e,n,t,a)})):(e.addEventListener(n,t,a),void w._handlers.push({remove:function(){return e.removeEventListener(n,t,a)}}))}function Y(){De("onChange")}function j(e,n){var t=void 0!==e?w.parseDate(e):w.latestSelectedDateObj||(w.config.minDate&&w.config.minDate>w.now?w.config.minDate:w.config.maxDate&&w.config.maxDate<w.now?w.config.maxDate:w.now),a=w.currentYear,i=w.currentMonth;try{void 0!==t&&(w.currentYear=t.getFullYear(),w.currentMonth=t.getMonth())}catch(e){e.message="Invalid date supplied: "+t,w.config.errorHandler(e)}n&&w.currentYear!==a&&(De("onYearChange"),q()),!n||w.currentYear===a&&w.currentMonth===i||De("onMonthChange"),w.redraw()}function H(e){var n=g(e);~n.className.indexOf("arrow")&&L(e,n.classList.contains("arrowUp")?1:-1)}function L(e,n,t){var a=e&&g(e),i=t||a&&a.parentNode&&a.parentNode.firstChild,o=we("increment");o.delta=n,i&&i.dispatchEvent(o)}function R(e,n,t,a){var i=ne(n,!0),o=d("span",e,n.getDate().toString());return o.dateObj=n,o.$i=a,o.setAttribute("aria-label",w.formatDate(n,w.config.ariaDateFormat)),-1===e.indexOf("hidden")&&0===M(n,w.now)&&(w.todayDateElem=o,o.classList.add("today"),o.setAttribute("aria-current","date")),i?(o.tabIndex=-1,be(n)&&(o.classList.add("selected"),w.selectedDateElem=o,"range"===w.config.mode&&(s(o,"startRange",w.selectedDates[0]&&0===M(n,w.selectedDates[0],!0)),s(o,"endRange",w.selectedDates[1]&&0===M(n,w.selectedDates[1],!0)),"nextMonthDay"===e&&o.classList.add("inRange")))):o.classList.add("flatpickr-disabled"),"range"===w.config.mode&&function(e){return!("range"!==w.config.mode||w.selectedDates.length<2)&&(M(e,w.selectedDates[0])>=0&&M(e,w.selectedDates[1])<=0)}(n)&&!be(n)&&o.classList.add("inRange"),w.weekNumbers&&1===w.config.showMonths&&"prevMonthDay"!==e&&a%7==6&&w.weekNumbers.insertAdjacentHTML("beforeend","<span class='flatpickr-day'>"+w.config.getWeek(n)+"</span>"),De("onDayCreate",o),o}function W(e){e.focus(),"range"===w.config.mode&&oe(e)}function B(e){for(var n=e>0?0:w.config.showMonths-1,t=e>0?w.config.showMonths:-1,a=n;a!=t;a+=e)for(var i=w.daysContainer.children[a],o=e>0?0:i.children.length-1,r=e>0?i.children.length:-1,l=o;l!=r;l+=e){var c=i.children[l];if(-1===c.className.indexOf("hidden")&&ne(c.dateObj))return c}}function J(e,n){var t=k(),a=te(t||document.body),i=void 0!==e?e:a?t:void 0!==w.selectedDateElem&&te(w.selectedDateElem)?w.selectedDateElem:void 0!==w.todayDateElem&&te(w.todayDateElem)?w.todayDateElem:B(n>0?1:-1);void 0===i?w._input.focus():a?function(e,n){for(var t=-1===e.className.indexOf("Month")?e.dateObj.getMonth():w.currentMonth,a=n>0?w.config.showMonths:-1,i=n>0?1:-1,o=t-w.currentMonth;o!=a;o+=i)for(var r=w.daysContainer.children[o],l=t-w.currentMonth===o?e.$i+n:n<0?r.children.length-1:0,c=r.children.length,s=l;s>=0&&s<c&&s!=(n>0?c:-1);s+=i){var d=r.children[s];if(-1===d.className.indexOf("hidden")&&ne(d.dateObj)&&Math.abs(e.$i-s)>=Math.abs(n))return W(d)}w.changeMonth(i),J(B(i),0)}(i,n):W(i)}function K(e,n){for(var t=(new Date(e,n,1).getDay()-w.l10n.firstDayOfWeek+7)%7,a=w.utils.getDaysInMonth((n-1+12)%12,e),i=w.utils.getDaysInMonth(n,e),o=window.document.createDocumentFragment(),r=w.config.showMonths>1,l=r?"prevMonthDay hidden":"prevMonthDay",c=r?"nextMonthDay hidden":"nextMonthDay",s=a+1-t,u=0;s<=a;s++,u++)o.appendChild(R("flatpickr-day "+l,new Date(e,n-1,s),0,u));for(s=1;s<=i;s++,u++)o.appendChild(R("flatpickr-day",new Date(e,n,s),0,u));for(var f=i+1;f<=42-t&&(1===w.config.showMonths||u%7!=0);f++,u++)o.appendChild(R("flatpickr-day "+c,new Date(e,n+1,f%i),0,u));var m=d("div","dayContainer");return m.appendChild(o),m}function U(){if(void 0!==w.daysContainer){u(w.daysContainer),w.weekNumbers&&u(w.weekNumbers);for(var e=document.createDocumentFragment(),n=0;n<w.config.showMonths;n++){var t=new Date(w.currentYear,w.currentMonth,1);t.setMonth(w.currentMonth+n),e.appendChild(K(t.getFullYear(),t.getMonth()))}w.daysContainer.appendChild(e),w.days=w.daysContainer.firstChild,"range"===w.config.mode&&1===w.selectedDates.length&&oe()}}function q(){if(!(w.config.showMonths>1||"dropdown"!==w.config.monthSelectorType)){var e=function(e){return!(void 0!==w.config.minDate&&w.currentYear===w.config.minDate.getFullYear()&&e<w.config.minDate.getMonth())&&!(void 0!==w.config.maxDate&&w.currentYear===w.config.maxDate.getFullYear()&&e>w.config.maxDate.getMonth())};w.monthsDropdownContainer.tabIndex=-1,w.monthsDropdownContainer.innerHTML="";for(var n=0;n<12;n++)if(e(n)){var t=d("option","flatpickr-monthDropdown-month");t.value=new Date(w.currentYear,n).getMonth().toString(),t.textContent=h(n,w.config.shorthandCurrentMonth,w.l10n),t.tabIndex=-1,w.currentMonth===n&&(t.selected=!0),w.monthsDropdownContainer.appendChild(t)}}}function $(){var e,n=d("div","flatpickr-month"),t=window.document.createDocumentFragment();w.config.showMonths>1||"static"===w.config.monthSelectorType?e=d("span","cur-month"):(w.monthsDropdownContainer=d("select","flatpickr-monthDropdown-months"),w.monthsDropdownContainer.setAttribute("aria-label",w.l10n.monthAriaLabel),P(w.monthsDropdownContainer,"change",(function(e){var n=g(e),t=parseInt(n.value,10);w.changeMonth(t-w.currentMonth),De("onMonthChange")})),q(),e=w.monthsDropdownContainer);var a=m("cur-year",{tabindex:"-1"}),i=a.getElementsByTagName("input")[0];i.setAttribute("aria-label",w.l10n.yearAriaLabel),w.config.minDate&&i.setAttribute("min",w.config.minDate.getFullYear().toString()),w.config.maxDate&&(i.setAttribute("max",w.config.maxDate.getFullYear().toString()),i.disabled=!!w.config.minDate&&w.config.minDate.getFullYear()===w.config.maxDate.getFullYear());var o=d("div","flatpickr-current-month");return o.appendChild(e),o.appendChild(a),t.appendChild(o),n.appendChild(t),{container:n,yearElement:i,monthElement:e}}function V(){u(w.monthNav),w.monthNav.appendChild(w.prevMonthNav),w.config.showMonths&&(w.yearElements=[],w.monthElements=[]);for(var e=w.config.showMonths;e--;){var n=$();w.yearElements.push(n.yearElement),w.monthElements.push(n.monthElement),w.monthNav.appendChild(n.container)}w.monthNav.appendChild(w.nextMonthNav)}function z(){w.weekdayContainer?u(w.weekdayContainer):w.weekdayContainer=d("div","flatpickr-weekdays");for(var e=w.config.showMonths;e--;){var n=d("div","flatpickr-weekdaycontainer");w.weekdayContainer.appendChild(n)}return G(),w.weekdayContainer}function G(){if(w.weekdayContainer){var e=w.l10n.firstDayOfWeek,t=n(w.l10n.weekdays.shorthand);e>0&&e<t.length&&(t=n(t.splice(e,t.length),t.splice(0,e)));for(var a=w.config.showMonths;a--;)w.weekdayContainer.children[a].innerHTML="\n <span class='flatpickr-weekday'>\n "+t.join("</span><span class='flatpickr-weekday'>")+"\n </span>\n "}}function Z(e,n){void 0===n&&(n=!0);var t=n?e:e-w.currentMonth;t<0&&!0===w._hidePrevMonthArrow||t>0&&!0===w._hideNextMonthArrow||(w.currentMonth+=t,(w.currentMonth<0||w.currentMonth>11)&&(w.currentYear+=w.currentMonth>11?1:-1,w.currentMonth=(w.currentMonth+12)%12,De("onYearChange"),q()),U(),De("onMonthChange"),Ce())}function Q(e){return w.calendarContainer.contains(e)}function X(e){if(w.isOpen&&!w.config.inline){var n=g(e),t=Q(n),a=!(n===w.input||n===w.altInput||w.element.contains(n)||e.path&&e.path.indexOf&&(~e.path.indexOf(w.input)||~e.path.indexOf(w.altInput)))&&!t&&!Q(e.relatedTarget),i=!w.config.ignoredFocusElements.some((function(e){return e.contains(n)}));a&&i&&(w.config.allowInput&&w.setDate(w._input.value,!1,w.config.altInput?w.config.altFormat:w.config.dateFormat),void 0!==w.timeContainer&&void 0!==w.minuteElement&&void 0!==w.hourElement&&""!==w.input.value&&void 0!==w.input.value&&_(),w.close(),w.config&&"range"===w.config.mode&&1===w.selectedDates.length&&w.clear(!1))}}function ee(e){if(!(!e||w.config.minDate&&e<w.config.minDate.getFullYear()||w.config.maxDate&&e>w.config.maxDate.getFullYear())){var n=e,t=w.currentYear!==n;w.currentYear=n||w.currentYear,w.config.maxDate&&w.currentYear===w.config.maxDate.getFullYear()?w.currentMonth=Math.min(w.config.maxDate.getMonth(),w.currentMonth):w.config.minDate&&w.currentYear===w.config.minDate.getFullYear()&&(w.currentMonth=Math.max(w.config.minDate.getMonth(),w.currentMonth)),t&&(w.redraw(),De("onYearChange"),q())}}function ne(e,n){var t;void 0===n&&(n=!0);var a=w.parseDate(e,void 0,n);if(w.config.minDate&&a&&M(a,w.config.minDate,void 0!==n?n:!w.minDateHasTime)<0||w.config.maxDate&&a&&M(a,w.config.maxDate,void 0!==n?n:!w.maxDateHasTime)>0)return!1;if(!w.config.enable&&0===w.config.disable.length)return!0;if(void 0===a)return!1;for(var i=!!w.config.enable,o=null!==(t=w.config.enable)&&void 0!==t?t:w.config.disable,r=0,l=void 0;r<o.length;r++){if("function"==typeof(l=o[r])&&l(a))return i;if(l instanceof Date&&void 0!==a&&l.getTime()===a.getTime())return i;if("string"==typeof l){var c=w.parseDate(l,void 0,!0);return c&&c.getTime()===a.getTime()?i:!i}if("object"==typeof l&&void 0!==a&&l.from&&l.to&&a.getTime()>=l.from.getTime()&&a.getTime()<=l.to.getTime())return i}return!i}function te(e){return void 0!==w.daysContainer&&(-1===e.className.indexOf("hidden")&&-1===e.className.indexOf("flatpickr-disabled")&&w.daysContainer.contains(e))}function ae(e){var n=e.target===w._input,t=w._input.value.trimEnd()!==Me();!n||!t||e.relatedTarget&&Q(e.relatedTarget)||w.setDate(w._input.value,!0,e.target===w.altInput?w.config.altFormat:w.config.dateFormat)}function ie(e){var n=g(e),t=w.config.wrap?p.contains(n):n===w._input,a=w.config.allowInput,i=w.isOpen&&(!a||!t),o=w.config.inline&&t&&!a;if(13===e.keyCode&&t){if(a)return w.setDate(w._input.value,!0,n===w.altInput?w.config.altFormat:w.config.dateFormat),w.close(),n.blur();w.open()}else if(Q(n)||i||o){var r=!!w.timeContainer&&w.timeContainer.contains(n);switch(e.keyCode){case 13:r?(e.preventDefault(),_(),fe()):me(e);break;case 27:e.preventDefault(),fe();break;case 8:case 46:t&&!w.config.allowInput&&(e.preventDefault(),w.clear());break;case 37:case 39:if(r||t)w.hourElement&&w.hourElement.focus();else{e.preventDefault();var l=k();if(void 0!==w.daysContainer&&(!1===a||l&&te(l))){var c=39===e.keyCode?1:-1;e.ctrlKey?(e.stopPropagation(),Z(c),J(B(1),0)):J(void 0,c)}}break;case 38:case 40:e.preventDefault();var s=40===e.keyCode?1:-1;w.daysContainer&&void 0!==n.$i||n===w.input||n===w.altInput?e.ctrlKey?(e.stopPropagation(),ee(w.currentYear-s),J(B(1),0)):r||J(void 0,7*s):n===w.currentYearElement?ee(w.currentYear-s):w.config.enableTime&&(!r&&w.hourElement&&w.hourElement.focus(),_(e),w._debouncedChange());break;case 9:if(r){var d=[w.hourElement,w.minuteElement,w.secondElement,w.amPM].concat(w.pluginElements).filter((function(e){return e})),u=d.indexOf(n);if(-1!==u){var f=d[u+(e.shiftKey?-1:1)];e.preventDefault(),(f||w._input).focus()}}else!w.config.noCalendar&&w.daysContainer&&w.daysContainer.contains(n)&&e.shiftKey&&(e.preventDefault(),w._input.focus())}}if(void 0!==w.amPM&&n===w.amPM)switch(e.key){case w.l10n.amPM[0].charAt(0):case w.l10n.amPM[0].charAt(0).toLowerCase():w.amPM.textContent=w.l10n.amPM[0],O(),ye();break;case w.l10n.amPM[1].charAt(0):case w.l10n.amPM[1].charAt(0).toLowerCase():w.amPM.textContent=w.l10n.amPM[1],O(),ye()}(t||Q(n))&&De("onKeyDown",e)}function oe(e,n){if(void 0===n&&(n="flatpickr-day"),1===w.selectedDates.length&&(!e||e.classList.contains(n)&&!e.classList.contains("flatpickr-disabled"))){for(var t=e?e.dateObj.getTime():w.days.firstElementChild.dateObj.getTime(),a=w.parseDate(w.selectedDates[0],void 0,!0).getTime(),i=Math.min(t,w.selectedDates[0].getTime()),o=Math.max(t,w.selectedDates[0].getTime()),r=!1,l=0,c=0,s=i;s<o;s+=x)ne(new Date(s),!0)||(r=r||s>i&&s<o,s<a&&(!l||s>l)?l=s:s>a&&(!c||s<c)&&(c=s));Array.from(w.rContainer.querySelectorAll("*:nth-child(-n+"+w.config.showMonths+") > ."+n)).forEach((function(n){var i,o,s,d=n.dateObj.getTime(),u=l>0&&d<l||c>0&&d>c;if(u)return n.classList.add("notAllowed"),void["inRange","startRange","endRange"].forEach((function(e){n.classList.remove(e)}));r&&!u||(["startRange","inRange","endRange","notAllowed"].forEach((function(e){n.classList.remove(e)})),void 0!==e&&(e.classList.add(t<=w.selectedDates[0].getTime()?"startRange":"endRange"),a<t&&d===a?n.classList.add("startRange"):a>t&&d===a&&n.classList.add("endRange"),d>=l&&(0===c||d<=c)&&(o=a,s=t,(i=d)>Math.min(o,s)&&i<Math.max(o,s))&&n.classList.add("inRange")))}))}}function re(){!w.isOpen||w.config.static||w.config.inline||de()}function le(e){return function(n){var t=w.config["_"+e+"Date"]=w.parseDate(n,w.config.dateFormat),a=w.config["_"+("min"===e?"max":"min")+"Date"];void 0!==t&&(w["min"===e?"minDateHasTime":"maxDateHasTime"]=t.getHours()>0||t.getMinutes()>0||t.getSeconds()>0),w.selectedDates&&(w.selectedDates=w.selectedDates.filter((function(e){return ne(e)})),w.selectedDates.length||"min"!==e||F(t),ye()),w.daysContainer&&(ue(),void 0!==t?w.currentYearElement[e]=t.getFullYear().toString():w.currentYearElement.removeAttribute(e),w.currentYearElement.disabled=!!a&&void 0!==t&&a.getFullYear()===t.getFullYear())}}function ce(){return w.config.wrap?p.querySelector("[data-input]"):p}function se(){"object"!=typeof w.config.locale&&void 0===I.l10ns[w.config.locale]&&w.config.errorHandler(new Error("flatpickr: invalid locale "+w.config.locale)),w.l10n=e(e({},I.l10ns.default),"object"==typeof w.config.locale?w.config.locale:"default"!==w.config.locale?I.l10ns[w.config.locale]:void 0),D.D="("+w.l10n.weekdays.shorthand.join("|")+")",D.l="("+w.l10n.weekdays.longhand.join("|")+")",D.M="("+w.l10n.months.shorthand.join("|")+")",D.F="("+w.l10n.months.longhand.join("|")+")",D.K="("+w.l10n.amPM[0]+"|"+w.l10n.amPM[1]+"|"+w.l10n.amPM[0].toLowerCase()+"|"+w.l10n.amPM[1].toLowerCase()+")",void 0===e(e({},v),JSON.parse(JSON.stringify(p.dataset||{}))).time_24hr&&void 0===I.defaultConfig.time_24hr&&(w.config.time_24hr=w.l10n.time_24hr),w.formatDate=b(w),w.parseDate=C({config:w.config,l10n:w.l10n})}function de(e){if("function"!=typeof w.config.position){if(void 0!==w.calendarContainer){De("onPreCalendarPosition");var n=e||w._positionElement,t=Array.prototype.reduce.call(w.calendarContainer.children,(function(e,n){return e+n.offsetHeight}),0),a=w.calendarContainer.offsetWidth,i=w.config.position.split(" "),o=i[0],r=i.length>1?i[1]:null,l=n.getBoundingClientRect(),c=window.innerHeight-l.bottom,d="above"===o||"below"!==o&&c<t&&l.top>t,u=window.pageYOffset+l.top+(d?-t-2:n.offsetHeight+2);if(s(w.calendarContainer,"arrowTop",!d),s(w.calendarContainer,"arrowBottom",d),!w.config.inline){var f=window.pageXOffset+l.left,m=!1,g=!1;"center"===r?(f-=(a-l.width)/2,m=!0):"right"===r&&(f-=a-l.width,g=!0),s(w.calendarContainer,"arrowLeft",!m&&!g),s(w.calendarContainer,"arrowCenter",m),s(w.calendarContainer,"arrowRight",g);var p=window.document.body.offsetWidth-(window.pageXOffset+l.right),h=f+a>window.document.body.offsetWidth,v=p+a>window.document.body.offsetWidth;if(s(w.calendarContainer,"rightMost",h),!w.config.static)if(w.calendarContainer.style.top=u+"px",h)if(v){var D=function(){for(var e=null,n=0;n<document.styleSheets.length;n++){var t=document.styleSheets[n];if(t.cssRules){try{t.cssRules}catch(e){continue}e=t;break}}return null!=e?e:(a=document.createElement("style"),document.head.appendChild(a),a.sheet);var a}();if(void 0===D)return;var b=window.document.body.offsetWidth,C=Math.max(0,b/2-a/2),M=D.cssRules.length,y="{left:"+l.left+"px;right:auto;}";s(w.calendarContainer,"rightMost",!1),s(w.calendarContainer,"centerMost",!0),D.insertRule(".flatpickr-calendar.centerMost:before,.flatpickr-calendar.centerMost:after"+y,M),w.calendarContainer.style.left=C+"px",w.calendarContainer.style.right="auto"}else w.calendarContainer.style.left="auto",w.calendarContainer.style.right=p+"px";else w.calendarContainer.style.left=f+"px",w.calendarContainer.style.right="auto"}}}else w.config.position(w,e)}function ue(){w.config.noCalendar||w.isMobile||(q(),Ce(),U())}function fe(){w._input.focus(),-1!==window.navigator.userAgent.indexOf("MSIE")||void 0!==navigator.msMaxTouchPoints?setTimeout(w.close,0):w.close()}function me(e){e.preventDefault(),e.stopPropagation();var n=f(g(e),(function(e){return e.classList&&e.classList.contains("flatpickr-day")&&!e.classList.contains("flatpickr-disabled")&&!e.classList.contains("notAllowed")}));if(void 0!==n){var t=n,a=w.latestSelectedDateObj=new Date(t.dateObj.getTime()),i=(a.getMonth()<w.currentMonth||a.getMonth()>w.currentMonth+w.config.showMonths-1)&&"range"!==w.config.mode;if(w.selectedDateElem=t,"single"===w.config.mode)w.selectedDates=[a];else if("multiple"===w.config.mode){var o=be(a);o?w.selectedDates.splice(parseInt(o),1):w.selectedDates.push(a)}else"range"===w.config.mode&&(2===w.selectedDates.length&&w.clear(!1,!1),w.latestSelectedDateObj=a,w.selectedDates.push(a),0!==M(a,w.selectedDates[0],!0)&&w.selectedDates.sort((function(e,n){return e.getTime()-n.getTime()})));if(O(),i){var r=w.currentYear!==a.getFullYear();w.currentYear=a.getFullYear(),w.currentMonth=a.getMonth(),r&&(De("onYearChange"),q()),De("onMonthChange")}if(Ce(),U(),ye(),i||"range"===w.config.mode||1!==w.config.showMonths?void 0!==w.selectedDateElem&&void 0===w.hourElement&&w.selectedDateElem&&w.selectedDateElem.focus():W(t),void 0!==w.hourElement&&void 0!==w.hourElement&&w.hourElement.focus(),w.config.closeOnSelect){var l="single"===w.config.mode&&!w.config.enableTime,c="range"===w.config.mode&&2===w.selectedDates.length&&!w.config.enableTime;(l||c)&&fe()}Y()}}w.parseDate=C({config:w.config,l10n:w.l10n}),w._handlers=[],w.pluginElements=[],w.loadedPlugins=[],w._bind=P,w._setHoursFromDate=F,w._positionCalendar=de,w.changeMonth=Z,w.changeYear=ee,w.clear=function(e,n){void 0===e&&(e=!0);void 0===n&&(n=!0);w.input.value="",void 0!==w.altInput&&(w.altInput.value="");void 0!==w.mobileInput&&(w.mobileInput.value="");w.selectedDates=[],w.latestSelectedDateObj=void 0,!0===n&&(w.currentYear=w._initialDate.getFullYear(),w.currentMonth=w._initialDate.getMonth());if(!0===w.config.enableTime){var t=E(w.config),a=t.hours,i=t.minutes,o=t.seconds;A(a,i,o)}w.redraw(),e&&De("onChange")},w.close=function(){w.isOpen=!1,w.isMobile||(void 0!==w.calendarContainer&&w.calendarContainer.classList.remove("open"),void 0!==w._input&&w._input.classList.remove("active"));De("onClose")},w.onMouseOver=oe,w._createElement=d,w.createDay=R,w.destroy=function(){void 0!==w.config&&De("onDestroy");for(var e=w._handlers.length;e--;)w._handlers[e].remove();if(w._handlers=[],w.mobileInput)w.mobileInput.parentNode&&w.mobileInput.parentNode.removeChild(w.mobileInput),w.mobileInput=void 0;else if(w.calendarContainer&&w.calendarContainer.parentNode)if(w.config.static&&w.calendarContainer.parentNode){var n=w.calendarContainer.parentNode;if(n.lastChild&&n.removeChild(n.lastChild),n.parentNode){for(;n.firstChild;)n.parentNode.insertBefore(n.firstChild,n);n.parentNode.removeChild(n)}}else w.calendarContainer.parentNode.removeChild(w.calendarContainer);w.altInput&&(w.input.type="text",w.altInput.parentNode&&w.altInput.parentNode.removeChild(w.altInput),delete w.altInput);w.input&&(w.input.type=w.input._type,w.input.classList.remove("flatpickr-input"),w.input.removeAttribute("readonly"));["_showTimeInput","latestSelectedDateObj","_hideNextMonthArrow","_hidePrevMonthArrow","__hideNextMonthArrow","__hidePrevMonthArrow","isMobile","isOpen","selectedDateElem","minDateHasTime","maxDateHasTime","days","daysContainer","_input","_positionElement","innerContainer","rContainer","monthNav","todayDateElem","calendarContainer","weekdayContainer","prevMonthNav","nextMonthNav","monthsDropdownContainer","currentMonthElement","currentYearElement","navigationCurrentMonth","selectedDateElem","config"].forEach((function(e){try{delete w[e]}catch(e){}}))},w.isEnabled=ne,w.jumpToDate=j,w.updateValue=ye,w.open=function(e,n){void 0===n&&(n=w._positionElement);if(!0===w.isMobile){if(e){e.preventDefault();var t=g(e);t&&t.blur()}return void 0!==w.mobileInput&&(w.mobileInput.focus(),w.mobileInput.click()),void De("onOpen")}if(w._input.disabled||w.config.inline)return;var a=w.isOpen;w.isOpen=!0,a||(w.calendarContainer.classList.add("open"),w._input.classList.add("active"),De("onOpen"),de(n));!0===w.config.enableTime&&!0===w.config.noCalendar&&(!1!==w.config.allowInput||void 0!==e&&w.timeContainer.contains(e.relatedTarget)||setTimeout((function(){return w.hourElement.select()}),50))},w.redraw=ue,w.set=function(e,n){if(null!==e&&"object"==typeof e)for(var a in Object.assign(w.config,e),e)void 0!==ge[a]&&ge[a].forEach((function(e){return e()}));else w.config[e]=n,void 0!==ge[e]?ge[e].forEach((function(e){return e()})):t.indexOf(e)>-1&&(w.config[e]=c(n));w.redraw(),ye(!0)},w.setDate=function(e,n,t){void 0===n&&(n=!1);void 0===t&&(t=w.config.dateFormat);if(0!==e&&!e||e instanceof Array&&0===e.length)return w.clear(n);pe(e,t),w.latestSelectedDateObj=w.selectedDates[w.selectedDates.length-1],w.redraw(),j(void 0,n),F(),0===w.selectedDates.length&&w.clear(!1);ye(n),n&&De("onChange")},w.toggle=function(e){if(!0===w.isOpen)return w.close();w.open(e)};var ge={locale:[se,G],showMonths:[V,S,z],minDate:[j],maxDate:[j],positionElement:[ve],clickOpens:[function(){!0===w.config.clickOpens?(P(w._input,"focus",w.open),P(w._input,"click",w.open)):(w._input.removeEventListener("focus",w.open),w._input.removeEventListener("click",w.open))}]};function pe(e,n){var t=[];if(e instanceof Array)t=e.map((function(e){return w.parseDate(e,n)}));else if(e instanceof Date||"number"==typeof e)t=[w.parseDate(e,n)];else if("string"==typeof e)switch(w.config.mode){case"single":case"time":t=[w.parseDate(e,n)];break;case"multiple":t=e.split(w.config.conjunction).map((function(e){return w.parseDate(e,n)}));break;case"range":t=e.split(w.l10n.rangeSeparator).map((function(e){return w.parseDate(e,n)}))}else w.config.errorHandler(new Error("Invalid date supplied: "+JSON.stringify(e)));w.selectedDates=w.config.allowInvalidPreload?t:t.filter((function(e){return e instanceof Date&&ne(e,!1)})),"range"===w.config.mode&&w.selectedDates.sort((function(e,n){return e.getTime()-n.getTime()}))}function he(e){return e.slice().map((function(e){return"string"==typeof e||"number"==typeof e||e instanceof Date?w.parseDate(e,void 0,!0):e&&"object"==typeof e&&e.from&&e.to?{from:w.parseDate(e.from,void 0),to:w.parseDate(e.to,void 0)}:e})).filter((function(e){return e}))}function ve(){w._positionElement=w.config.positionElement||w._input}function De(e,n){if(void 0!==w.config){var t=w.config[e];if(void 0!==t&&t.length>0)for(var a=0;t[a]&&a<t.length;a++)t[a](w.selectedDates,w.input.value,w,n);"onChange"===e&&(w.input.dispatchEvent(we("change")),w.input.dispatchEvent(we("input")))}}function we(e){var n=document.createEvent("Event");return n.initEvent(e,!0,!0),n}function be(e){for(var n=0;n<w.selectedDates.length;n++){var t=w.selectedDates[n];if(t instanceof Date&&0===M(t,e))return""+n}return!1}function Ce(){w.config.noCalendar||w.isMobile||!w.monthNav||(w.yearElements.forEach((function(e,n){var t=new Date(w.currentYear,w.currentMonth,1);t.setMonth(w.currentMonth+n),w.config.showMonths>1||"static"===w.config.monthSelectorType?w.monthElements[n].textContent=h(t.getMonth(),w.config.shorthandCurrentMonth,w.l10n)+" ":w.monthsDropdownContainer.value=t.getMonth().toString(),e.value=t.getFullYear().toString()})),w._hidePrevMonthArrow=void 0!==w.config.minDate&&(w.currentYear===w.config.minDate.getFullYear()?w.currentMonth<=w.config.minDate.getMonth():w.currentYear<w.config.minDate.getFullYear()),w._hideNextMonthArrow=void 0!==w.config.maxDate&&(w.currentYear===w.config.maxDate.getFullYear()?w.currentMonth+1>w.config.maxDate.getMonth():w.currentYear>w.config.maxDate.getFullYear()))}function Me(e){var n=e||(w.config.altInput?w.config.altFormat:w.config.dateFormat);return w.selectedDates.map((function(e){return w.formatDate(e,n)})).filter((function(e,n,t){return"range"!==w.config.mode||w.config.enableTime||t.indexOf(e)===n})).join("range"!==w.config.mode?w.config.conjunction:w.l10n.rangeSeparator)}function ye(e){void 0===e&&(e=!0),void 0!==w.mobileInput&&w.mobileFormatStr&&(w.mobileInput.value=void 0!==w.latestSelectedDateObj?w.formatDate(w.latestSelectedDateObj,w.mobileFormatStr):""),w.input.value=Me(w.config.dateFormat),void 0!==w.altInput&&(w.altInput.value=Me(w.config.altFormat)),!1!==e&&De("onValueUpdate")}function xe(e){var n=g(e),t=w.prevMonthNav.contains(n),a=w.nextMonthNav.contains(n);t||a?Z(t?-1:1):w.yearElements.indexOf(n)>=0?n.select():n.classList.contains("arrowUp")?w.changeYear(w.currentYear+1):n.classList.contains("arrowDown")&&w.changeYear(w.currentYear-1)}return function(){w.element=w.input=p,w.isOpen=!1,function(){var n=["wrap","weekNumbers","allowInput","allowInvalidPreload","clickOpens","time_24hr","enableTime","noCalendar","altInput","shorthandCurrentMonth","inline","static","enableSeconds","disableMobile"],i=e(e({},JSON.parse(JSON.stringify(p.dataset||{}))),v),o={};w.config.parseDate=i.parseDate,w.config.formatDate=i.formatDate,Object.defineProperty(w.config,"enable",{get:function(){return w.config._enable},set:function(e){w.config._enable=he(e)}}),Object.defineProperty(w.config,"disable",{get:function(){return w.config._disable},set:function(e){w.config._disable=he(e)}});var r="time"===i.mode;if(!i.dateFormat&&(i.enableTime||r)){var l=I.defaultConfig.dateFormat||a.dateFormat;o.dateFormat=i.noCalendar||r?"H:i"+(i.enableSeconds?":S":""):l+" H:i"+(i.enableSeconds?":S":"")}if(i.altInput&&(i.enableTime||r)&&!i.altFormat){var s=I.defaultConfig.altFormat||a.altFormat;o.altFormat=i.noCalendar||r?"h:i"+(i.enableSeconds?":S K":" K"):s+" h:i"+(i.enableSeconds?":S":"")+" K"}Object.defineProperty(w.config,"minDate",{get:function(){return w.config._minDate},set:le("min")}),Object.defineProperty(w.config,"maxDate",{get:function(){return w.config._maxDate},set:le("max")});var d=function(e){return function(n){w.config["min"===e?"_minTime":"_maxTime"]=w.parseDate(n,"H:i:S")}};Object.defineProperty(w.config,"minTime",{get:function(){return w.config._minTime},set:d("min")}),Object.defineProperty(w.config,"maxTime",{get:function(){return w.config._maxTime},set:d("max")}),"time"===i.mode&&(w.config.noCalendar=!0,w.config.enableTime=!0);Object.assign(w.config,o,i);for(var u=0;u<n.length;u++)w.config[n[u]]=!0===w.config[n[u]]||"true"===w.config[n[u]];t.filter((function(e){return void 0!==w.config[e]})).forEach((function(e){w.config[e]=c(w.config[e]||[]).map(T)})),w.isMobile=!w.config.disableMobile&&!w.config.inline&&"single"===w.config.mode&&!w.config.disable.length&&!w.config.enable&&!w.config.weekNumbers&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);for(u=0;u<w.config.plugins.length;u++){var f=w.config.plugins[u](w)||{};for(var m in f)t.indexOf(m)>-1?w.config[m]=c(f[m]).map(T).concat(w.config[m]):void 0===i[m]&&(w.config[m]=f[m])}i.altInputClass||(w.config.altInputClass=ce().className+" "+w.config.altInputClass);De("onParseConfig")}(),se(),function(){if(w.input=ce(),!w.input)return void w.config.errorHandler(new Error("Invalid input element specified"));w.input._type=w.input.type,w.input.type="text",w.input.classList.add("flatpickr-input"),w._input=w.input,w.config.altInput&&(w.altInput=d(w.input.nodeName,w.config.altInputClass),w._input=w.altInput,w.altInput.placeholder=w.input.placeholder,w.altInput.disabled=w.input.disabled,w.altInput.required=w.input.required,w.altInput.tabIndex=w.input.tabIndex,w.altInput.type="text",w.input.setAttribute("type","hidden"),!w.config.static&&w.input.parentNode&&w.input.parentNode.insertBefore(w.altInput,w.input.nextSibling));w.config.allowInput||w._input.setAttribute("readonly","readonly");ve()}(),function(){w.selectedDates=[],w.now=w.parseDate(w.config.now)||new Date;var e=w.config.defaultDate||("INPUT"!==w.input.nodeName&&"TEXTAREA"!==w.input.nodeName||!w.input.placeholder||w.input.value!==w.input.placeholder?w.input.value:null);e&&pe(e,w.config.dateFormat);w._initialDate=w.selectedDates.length>0?w.selectedDates[0]:w.config.minDate&&w.config.minDate.getTime()>w.now.getTime()?w.config.minDate:w.config.maxDate&&w.config.maxDate.getTime()<w.now.getTime()?w.config.maxDate:w.now,w.currentYear=w._initialDate.getFullYear(),w.currentMonth=w._initialDate.getMonth(),w.selectedDates.length>0&&(w.latestSelectedDateObj=w.selectedDates[0]);void 0!==w.config.minTime&&(w.config.minTime=w.parseDate(w.config.minTime,"H:i"));void 0!==w.config.maxTime&&(w.config.maxTime=w.parseDate(w.config.maxTime,"H:i"));w.minDateHasTime=!!w.config.minDate&&(w.config.minDate.getHours()>0||w.config.minDate.getMinutes()>0||w.config.minDate.getSeconds()>0),w.maxDateHasTime=!!w.config.maxDate&&(w.config.maxDate.getHours()>0||w.config.maxDate.getMinutes()>0||w.config.maxDate.getSeconds()>0)}(),w.utils={getDaysInMonth:function(e,n){return void 0===e&&(e=w.currentMonth),void 0===n&&(n=w.currentYear),1===e&&(n%4==0&&n%100!=0||n%400==0)?29:w.l10n.daysInMonth[e]}},w.isMobile||function(){var e=window.document.createDocumentFragment();if(w.calendarContainer=d("div","flatpickr-calendar"),w.calendarContainer.tabIndex=-1,!w.config.noCalendar){if(e.appendChild((w.monthNav=d("div","flatpickr-months"),w.yearElements=[],w.monthElements=[],w.prevMonthNav=d("span","flatpickr-prev-month"),w.prevMonthNav.innerHTML=w.config.prevArrow,w.nextMonthNav=d("span","flatpickr-next-month"),w.nextMonthNav.innerHTML=w.config.nextArrow,V(),Object.defineProperty(w,"_hidePrevMonthArrow",{get:function(){return w.__hidePrevMonthArrow},set:function(e){w.__hidePrevMonthArrow!==e&&(s(w.prevMonthNav,"flatpickr-disabled",e),w.__hidePrevMonthArrow=e)}}),Object.defineProperty(w,"_hideNextMonthArrow",{get:function(){return w.__hideNextMonthArrow},set:function(e){w.__hideNextMonthArrow!==e&&(s(w.nextMonthNav,"flatpickr-disabled",e),w.__hideNextMonthArrow=e)}}),w.currentYearElement=w.yearElements[0],Ce(),w.monthNav)),w.innerContainer=d("div","flatpickr-innerContainer"),w.config.weekNumbers){var n=function(){w.calendarContainer.classList.add("hasWeeks");var e=d("div","flatpickr-weekwrapper");e.appendChild(d("span","flatpickr-weekday",w.l10n.weekAbbreviation));var n=d("div","flatpickr-weeks");return e.appendChild(n),{weekWrapper:e,weekNumbers:n}}(),t=n.weekWrapper,a=n.weekNumbers;w.innerContainer.appendChild(t),w.weekNumbers=a,w.weekWrapper=t}w.rContainer=d("div","flatpickr-rContainer"),w.rContainer.appendChild(z()),w.daysContainer||(w.daysContainer=d("div","flatpickr-days"),w.daysContainer.tabIndex=-1),U(),w.rContainer.appendChild(w.daysContainer),w.innerContainer.appendChild(w.rContainer),e.appendChild(w.innerContainer)}w.config.enableTime&&e.appendChild(function(){w.calendarContainer.classList.add("hasTime"),w.config.noCalendar&&w.calendarContainer.classList.add("noCalendar");var e=E(w.config);w.timeContainer=d("div","flatpickr-time"),w.timeContainer.tabIndex=-1;var n=d("span","flatpickr-time-separator",":"),t=m("flatpickr-hour",{"aria-label":w.l10n.hourAriaLabel});w.hourElement=t.getElementsByTagName("input")[0];var a=m("flatpickr-minute",{"aria-label":w.l10n.minuteAriaLabel});w.minuteElement=a.getElementsByTagName("input")[0],w.hourElement.tabIndex=w.minuteElement.tabIndex=-1,w.hourElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getHours():w.config.time_24hr?e.hours:function(e){switch(e%24){case 0:case 12:return 12;default:return e%12}}(e.hours)),w.minuteElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getMinutes():e.minutes),w.hourElement.setAttribute("step",w.config.hourIncrement.toString()),w.minuteElement.setAttribute("step",w.config.minuteIncrement.toString()),w.hourElement.setAttribute("min",w.config.time_24hr?"0":"1"),w.hourElement.setAttribute("max",w.config.time_24hr?"23":"12"),w.hourElement.setAttribute("maxlength","2"),w.minuteElement.setAttribute("min","0"),w.minuteElement.setAttribute("max","59"),w.minuteElement.setAttribute("maxlength","2"),w.timeContainer.appendChild(t),w.timeContainer.appendChild(n),w.timeContainer.appendChild(a),w.config.time_24hr&&w.timeContainer.classList.add("time24hr");if(w.config.enableSeconds){w.timeContainer.classList.add("hasSeconds");var i=m("flatpickr-second");w.secondElement=i.getElementsByTagName("input")[0],w.secondElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getSeconds():e.seconds),w.secondElement.setAttribute("step",w.minuteElement.getAttribute("step")),w.secondElement.setAttribute("min","0"),w.secondElement.setAttribute("max","59"),w.secondElement.setAttribute("maxlength","2"),w.timeContainer.appendChild(d("span","flatpickr-time-separator",":")),w.timeContainer.appendChild(i)}w.config.time_24hr||(w.amPM=d("span","flatpickr-am-pm",w.l10n.amPM[r((w.latestSelectedDateObj?w.hourElement.value:w.config.defaultHour)>11)]),w.amPM.title=w.l10n.toggleTitle,w.amPM.tabIndex=-1,w.timeContainer.appendChild(w.amPM));return w.timeContainer}());s(w.calendarContainer,"rangeMode","range"===w.config.mode),s(w.calendarContainer,"animate",!0===w.config.animate),s(w.calendarContainer,"multiMonth",w.config.showMonths>1),w.calendarContainer.appendChild(e);var i=void 0!==w.config.appendTo&&void 0!==w.config.appendTo.nodeType;if((w.config.inline||w.config.static)&&(w.calendarContainer.classList.add(w.config.inline?"inline":"static"),w.config.inline&&(!i&&w.element.parentNode?w.element.parentNode.insertBefore(w.calendarContainer,w._input.nextSibling):void 0!==w.config.appendTo&&w.config.appendTo.appendChild(w.calendarContainer)),w.config.static)){var l=d("div","flatpickr-wrapper");w.element.parentNode&&w.element.parentNode.insertBefore(l,w.element),l.appendChild(w.element),w.altInput&&l.appendChild(w.altInput),l.appendChild(w.calendarContainer)}w.config.static||w.config.inline||(void 0!==w.config.appendTo?w.config.appendTo:window.document.body).appendChild(w.calendarContainer)}(),function(){w.config.wrap&&["open","close","toggle","clear"].forEach((function(e){Array.prototype.forEach.call(w.element.querySelectorAll("[data-"+e+"]"),(function(n){return P(n,"click",w[e])}))}));if(w.isMobile)return void function(){var e=w.config.enableTime?w.config.noCalendar?"time":"datetime-local":"date";w.mobileInput=d("input",w.input.className+" flatpickr-mobile"),w.mobileInput.tabIndex=1,w.mobileInput.type=e,w.mobileInput.disabled=w.input.disabled,w.mobileInput.required=w.input.required,w.mobileInput.placeholder=w.input.placeholder,w.mobileFormatStr="datetime-local"===e?"Y-m-d\\TH:i:S":"date"===e?"Y-m-d":"H:i:S",w.selectedDates.length>0&&(w.mobileInput.defaultValue=w.mobileInput.value=w.formatDate(w.selectedDates[0],w.mobileFormatStr));w.config.minDate&&(w.mobileInput.min=w.formatDate(w.config.minDate,"Y-m-d"));w.config.maxDate&&(w.mobileInput.max=w.formatDate(w.config.maxDate,"Y-m-d"));w.input.getAttribute("step")&&(w.mobileInput.step=String(w.input.getAttribute("step")));w.input.type="hidden",void 0!==w.altInput&&(w.altInput.type="hidden");try{w.input.parentNode&&w.input.parentNode.insertBefore(w.mobileInput,w.input.nextSibling)}catch(e){}P(w.mobileInput,"change",(function(e){w.setDate(g(e).value,!1,w.mobileFormatStr),De("onChange"),De("onClose")}))}();var e=l(re,50);w._debouncedChange=l(Y,300),w.daysContainer&&!/iPhone|iPad|iPod/i.test(navigator.userAgent)&&P(w.daysContainer,"mouseover",(function(e){"range"===w.config.mode&&oe(g(e))}));P(w._input,"keydown",ie),void 0!==w.calendarContainer&&P(w.calendarContainer,"keydown",ie);w.config.inline||w.config.static||P(window,"resize",e);void 0!==window.ontouchstart?P(window.document,"touchstart",X):P(window.document,"mousedown",X);P(window.document,"focus",X,{capture:!0}),!0===w.config.clickOpens&&(P(w._input,"focus",w.open),P(w._input,"click",w.open));void 0!==w.daysContainer&&(P(w.monthNav,"click",xe),P(w.monthNav,["keyup","increment"],N),P(w.daysContainer,"click",me));if(void 0!==w.timeContainer&&void 0!==w.minuteElement&&void 0!==w.hourElement){var n=function(e){return g(e).select()};P(w.timeContainer,["increment"],_),P(w.timeContainer,"blur",_,{capture:!0}),P(w.timeContainer,"click",H),P([w.hourElement,w.minuteElement],["focus","click"],n),void 0!==w.secondElement&&P(w.secondElement,"focus",(function(){return w.secondElement&&w.secondElement.select()})),void 0!==w.amPM&&P(w.amPM,"click",(function(e){_(e)}))}w.config.allowInput&&P(w._input,"blur",ae)}(),(w.selectedDates.length||w.config.noCalendar)&&(w.config.enableTime&&F(w.config.noCalendar?w.latestSelectedDateObj:void 0),ye(!1)),S();var n=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);!w.isMobile&&n&&de(),De("onReady")}(),w}function T(e,n){for(var t=Array.prototype.slice.call(e).filter((function(e){return e instanceof HTMLElement})),a=[],i=0;i<t.length;i++){var o=t[i];try{if(null!==o.getAttribute("data-fp-omit"))continue;void 0!==o._flatpickr&&(o._flatpickr.destroy(),o._flatpickr=void 0),o._flatpickr=k(o,n||{}),a.push(o._flatpickr)}catch(e){console.error(e)}}return 1===a.length?a[0]:a}"undefined"!=typeof HTMLElement&&"undefined"!=typeof HTMLCollection&&"undefined"!=typeof NodeList&&(HTMLCollection.prototype.flatpickr=NodeList.prototype.flatpickr=function(e){return T(this,e)},HTMLElement.prototype.flatpickr=function(e){return T([this],e)});var I=function(e,n){return"string"==typeof e?T(window.document.querySelectorAll(e),n):e instanceof Node?T([e],n):T(e,n)};return I.defaultConfig={},I.l10ns={en:e({},i),default:e({},i)},I.localize=function(n){I.l10ns.default=e(e({},I.l10ns.default),n)},I.setDefaults=function(n){I.defaultConfig=e(e({},I.defaultConfig),n)},I.parseDate=C({}),I.formatDate=b({}),I.compareDates=M,"undefined"!=typeof jQuery&&void 0!==jQuery.fn&&(jQuery.fn.flatpickr=function(e){return T(this,e)}),Date.prototype.fp_incr=function(e){return new Date(this.getFullYear(),this.getMonth(),this.getDate()+("string"==typeof e?parseInt(e,10):e))},"undefined"!=typeof window&&(window.flatpickr=I),I})); +/*! Select2 4.1.0-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */ +!function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),n(t),t}:n(jQuery)}(function(t){var e,n,s,p,r,o,h,f,g,m,y,v,i,a,_,s=((u=t&&t.fn&&t.fn.select2&&t.fn.select2.amd?t.fn.select2.amd:u)&&u.requirejs||(u?n=u:u={},g={},m={},y={},v={},i=Object.prototype.hasOwnProperty,a=[].slice,_=/\.js$/,h=function(e,t){var n,s,i=c(e),r=i[0],t=t[1];return e=i[1],r&&(n=x(r=l(r,t))),r?e=n&&n.normalize?n.normalize(e,(s=t,function(e){return l(e,s)})):l(e,t):(r=(i=c(e=l(e,t)))[0],e=i[1],r&&(n=x(r))),{f:r?r+"!"+e:e,n:e,pr:r,p:n}},f={require:function(e){return w(e)},exports:function(e){var t=g[e];return void 0!==t?t:g[e]={}},module:function(e){return{id:e,uri:"",exports:g[e],config:(t=e,function(){return y&&y.config&&y.config[t]||{}})};var t}},r=function(e,t,n,s){var i,r,o,a,l,c=[],u=typeof n,d=A(s=s||e);if("undefined"==u||"function"==u){for(t=!t.length&&n.length?["require","exports","module"]:t,a=0;a<t.length;a+=1)if("require"===(r=(o=h(t[a],d)).f))c[a]=f.require(e);else if("exports"===r)c[a]=f.exports(e),l=!0;else if("module"===r)i=c[a]=f.module(e);else if(b(g,r)||b(m,r)||b(v,r))c[a]=x(r);else{if(!o.p)throw new Error(e+" missing "+r);o.p.load(o.n,w(s,!0),function(t){return function(e){g[t]=e}}(r),{}),c[a]=g[r]}u=n?n.apply(g[e],c):void 0,e&&(i&&i.exports!==p&&i.exports!==g[e]?g[e]=i.exports:u===p&&l||(g[e]=u))}else e&&(g[e]=n)},e=n=o=function(e,t,n,s,i){if("string"==typeof e)return f[e]?f[e](t):x(h(e,A(t)).f);if(!e.splice){if((y=e).deps&&o(y.deps,y.callback),!t)return;t.splice?(e=t,t=n,n=null):e=p}return t=t||function(){},"function"==typeof n&&(n=s,s=i),s?r(p,e,t,n):setTimeout(function(){r(p,e,t,n)},4),o},o.config=function(e){return o(e)},e._defined=g,(s=function(e,t,n){if("string"!=typeof e)throw new Error("See almond README: incorrect module build, no module name");t.splice||(n=t,t=[]),b(g,e)||b(m,e)||(m[e]=[e,t,n])}).amd={jQuery:!0},u.requirejs=e,u.require=n,u.define=s),u.define("almond",function(){}),u.define("jquery",[],function(){var e=t||$;return null==e&&console&&console.error&&console.error("Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page."),e}),u.define("select2/utils",["jquery"],function(r){var s={};function c(e){var t,n=e.prototype,s=[];for(t in n)"function"==typeof n[t]&&"constructor"!==t&&s.push(t);return s}s.Extend=function(e,t){var n,s={}.hasOwnProperty;function i(){this.constructor=e}for(n in t)s.call(t,n)&&(e[n]=t[n]);return i.prototype=t.prototype,e.prototype=new i,e.__super__=t.prototype,e},s.Decorate=function(s,i){var e=c(i),t=c(s);function r(){var e=Array.prototype.unshift,t=i.prototype.constructor.length,n=s.prototype.constructor;0<t&&(e.call(arguments,s.prototype.constructor),n=i.prototype.constructor),n.apply(this,arguments)}i.displayName=s.displayName,r.prototype=new function(){this.constructor=r};for(var n=0;n<t.length;n++){var o=t[n];r.prototype[o]=s.prototype[o]}for(var a=0;a<e.length;a++){var l=e[a];r.prototype[l]=function(e){var t=function(){};e in r.prototype&&(t=r.prototype[e]);var n=i.prototype[e];return function(){return Array.prototype.unshift.call(arguments,t),n.apply(this,arguments)}}(l)}return r};function e(){this.listeners={}}e.prototype.on=function(e,t){this.listeners=this.listeners||{},e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t]},e.prototype.trigger=function(e){var t=Array.prototype.slice,n=t.call(arguments,1);this.listeners=this.listeners||{},0===(n=null==n?[]:n).length&&n.push({}),(n[0]._type=e)in this.listeners&&this.invoke(this.listeners[e],t.call(arguments,1)),"*"in this.listeners&&this.invoke(this.listeners["*"],arguments)},e.prototype.invoke=function(e,t){for(var n=0,s=e.length;n<s;n++)e[n].apply(this,t)},s.Observable=e,s.generateChars=function(e){for(var t="",n=0;n<e;n++)t+=Math.floor(36*Math.random()).toString(36);return t},s.bind=function(e,t){return function(){e.apply(t,arguments)}},s._convertData=function(e){for(var t in e){var n=t.split("-"),s=e;if(1!==n.length){for(var i=0;i<n.length;i++){var r=n[i];(r=r.substring(0,1).toLowerCase()+r.substring(1))in s||(s[r]={}),i==n.length-1&&(s[r]=e[t]),s=s[r]}delete e[t]}}return e},s.hasScroll=function(e,t){var n=r(t),s=t.style.overflowX,i=t.style.overflowY;return(s!==i||"hidden"!==i&&"visible"!==i)&&("scroll"===s||"scroll"===i||(n.innerHeight()<t.scrollHeight||n.innerWidth()<t.scrollWidth))},s.escapeMarkup=function(e){var t={"\\":"\","&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};return"string"!=typeof e?e:String(e).replace(/[&<>"'\/\\]/g,function(e){return t[e]})},s.__cache={};var n=0;return s.GetUniqueElementId=function(e){var t=e.getAttribute("data-select2-id");return null!=t||(t=e.id?"select2-data-"+e.id:"select2-data-"+(++n).toString()+"-"+s.generateChars(4),e.setAttribute("data-select2-id",t)),t},s.StoreData=function(e,t,n){e=s.GetUniqueElementId(e);s.__cache[e]||(s.__cache[e]={}),s.__cache[e][t]=n},s.GetData=function(e,t){var n=s.GetUniqueElementId(e);return t?s.__cache[n]&&null!=s.__cache[n][t]?s.__cache[n][t]:r(e).data(t):s.__cache[n]},s.RemoveData=function(e){var t=s.GetUniqueElementId(e);null!=s.__cache[t]&&delete s.__cache[t],e.removeAttribute("data-select2-id")},s.copyNonInternalCssClasses=function(e,t){var n=(n=e.getAttribute("class").trim().split(/\s+/)).filter(function(e){return 0===e.indexOf("select2-")}),t=(t=t.getAttribute("class").trim().split(/\s+/)).filter(function(e){return 0!==e.indexOf("select2-")}),t=n.concat(t);e.setAttribute("class",t.join(" "))},s}),u.define("select2/results",["jquery","./utils"],function(d,p){function s(e,t,n){this.$element=e,this.data=n,this.options=t,s.__super__.constructor.call(this)}return p.Extend(s,p.Observable),s.prototype.render=function(){var e=d('<ul class="select2-results__options" role="listbox"></ul>');return this.options.get("multiple")&&e.attr("aria-multiselectable","true"),this.$results=e},s.prototype.clear=function(){this.$results.empty()},s.prototype.displayMessage=function(e){var t=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var n=d('<li role="alert" aria-live="assertive" class="select2-results__option"></li>'),s=this.options.get("translations").get(e.message);n.append(t(s(e.args))),n[0].className+=" select2-results__message",this.$results.append(n)},s.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},s.prototype.append=function(e){this.hideLoading();var t=[];if(null!=e.results&&0!==e.results.length){e.results=this.sort(e.results);for(var n=0;n<e.results.length;n++){var s=e.results[n],s=this.option(s);t.push(s)}this.$results.append(t)}else 0===this.$results.children().length&&this.trigger("results:message",{message:"noResults"})},s.prototype.position=function(e,t){t.find(".select2-results").append(e)},s.prototype.sort=function(e){return this.options.get("sorter")(e)},s.prototype.highlightFirstItem=function(){var e=this.$results.find(".select2-results__option--selectable"),t=e.filter(".select2-results__option--selected");(0<t.length?t:e).first().trigger("mouseenter"),this.ensureHighlightVisible()},s.prototype.setClasses=function(){var t=this;this.data.current(function(e){var s=e.map(function(e){return e.id.toString()});t.$results.find(".select2-results__option--selectable").each(function(){var e=d(this),t=p.GetData(this,"data"),n=""+t.id;null!=t.element&&t.element.selected||null==t.element&&-1<s.indexOf(n)?(this.classList.add("select2-results__option--selected"),e.attr("aria-selected","true")):(this.classList.remove("select2-results__option--selected"),e.attr("aria-selected","false"))})})},s.prototype.showLoading=function(e){this.hideLoading();e={disabled:!0,loading:!0,text:this.options.get("translations").get("searching")(e)},e=this.option(e);e.className+=" loading-results",this.$results.prepend(e)},s.prototype.hideLoading=function(){this.$results.find(".loading-results").remove()},s.prototype.option=function(e){var t=document.createElement("li");t.classList.add("select2-results__option"),t.classList.add("select2-results__option--selectable");var n,s={role:"option"},i=window.Element.prototype.matches||window.Element.prototype.msMatchesSelector||window.Element.prototype.webkitMatchesSelector;for(n in(null!=e.element&&i.call(e.element,":disabled")||null==e.element&&e.disabled)&&(s["aria-disabled"]="true",t.classList.remove("select2-results__option--selectable"),t.classList.add("select2-results__option--disabled")),null==e.id&&t.classList.remove("select2-results__option--selectable"),null!=e._resultId&&(t.id=e._resultId),e.title&&(t.title=e.title),e.children&&(s.role="group",s["aria-label"]=e.text,t.classList.remove("select2-results__option--selectable"),t.classList.add("select2-results__option--group")),s){var r=s[n];t.setAttribute(n,r)}if(e.children){var o=d(t),a=document.createElement("strong");a.className="select2-results__group",this.template(e,a);for(var l=[],c=0;c<e.children.length;c++){var u=e.children[c],u=this.option(u);l.push(u)}i=d("<ul></ul>",{class:"select2-results__options select2-results__options--nested",role:"none"});i.append(l),o.append(a),o.append(i)}else this.template(e,t);return p.StoreData(t,"data",e),t},s.prototype.bind=function(t,e){var i=this,n=t.id+"-results";this.$results.attr("id",n),t.on("results:all",function(e){i.clear(),i.append(e.data),t.isOpen()&&(i.setClasses(),i.highlightFirstItem())}),t.on("results:append",function(e){i.append(e.data),t.isOpen()&&i.setClasses()}),t.on("query",function(e){i.hideMessages(),i.showLoading(e)}),t.on("select",function(){t.isOpen()&&(i.setClasses(),i.options.get("scrollAfterSelect")&&i.highlightFirstItem())}),t.on("unselect",function(){t.isOpen()&&(i.setClasses(),i.options.get("scrollAfterSelect")&&i.highlightFirstItem())}),t.on("open",function(){i.$results.attr("aria-expanded","true"),i.$results.attr("aria-hidden","false"),i.setClasses(),i.ensureHighlightVisible()}),t.on("close",function(){i.$results.attr("aria-expanded","false"),i.$results.attr("aria-hidden","true"),i.$results.removeAttr("aria-activedescendant")}),t.on("results:toggle",function(){var e=i.getHighlightedResults();0!==e.length&&e.trigger("mouseup")}),t.on("results:select",function(){var e,t=i.getHighlightedResults();0!==t.length&&(e=p.GetData(t[0],"data"),t.hasClass("select2-results__option--selected")?i.trigger("close",{}):i.trigger("select",{data:e}))}),t.on("results:previous",function(){var e,t=i.getHighlightedResults(),n=i.$results.find(".select2-results__option--selectable"),s=n.index(t);s<=0||(e=s-1,0===t.length&&(e=0),(s=n.eq(e)).trigger("mouseenter"),t=i.$results.offset().top,n=s.offset().top,s=i.$results.scrollTop()+(n-t),0===e?i.$results.scrollTop(0):n-t<0&&i.$results.scrollTop(s))}),t.on("results:next",function(){var e,t=i.getHighlightedResults(),n=i.$results.find(".select2-results__option--selectable"),s=n.index(t)+1;s>=n.length||((e=n.eq(s)).trigger("mouseenter"),t=i.$results.offset().top+i.$results.outerHeight(!1),n=e.offset().top+e.outerHeight(!1),e=i.$results.scrollTop()+n-t,0===s?i.$results.scrollTop(0):t<n&&i.$results.scrollTop(e))}),t.on("results:focus",function(e){e.element[0].classList.add("select2-results__option--highlighted"),e.element[0].setAttribute("aria-selected","true")}),t.on("results:message",function(e){i.displayMessage(e)}),d.fn.mousewheel&&this.$results.on("mousewheel",function(e){var t=i.$results.scrollTop(),n=i.$results.get(0).scrollHeight-t+e.deltaY,t=0<e.deltaY&&t-e.deltaY<=0,n=e.deltaY<0&&n<=i.$results.height();t?(i.$results.scrollTop(0),e.preventDefault(),e.stopPropagation()):n&&(i.$results.scrollTop(i.$results.get(0).scrollHeight-i.$results.height()),e.preventDefault(),e.stopPropagation())}),this.$results.on("mouseup",".select2-results__option--selectable",function(e){var t=d(this),n=p.GetData(this,"data");t.hasClass("select2-results__option--selected")?i.options.get("multiple")?i.trigger("unselect",{originalEvent:e,data:n}):i.trigger("close",{}):i.trigger("select",{originalEvent:e,data:n})}),this.$results.on("mouseenter",".select2-results__option--selectable",function(e){var t=p.GetData(this,"data");i.getHighlightedResults().removeClass("select2-results__option--highlighted").attr("aria-selected","false"),i.trigger("results:focus",{data:t,element:d(this)})})},s.prototype.getHighlightedResults=function(){return this.$results.find(".select2-results__option--highlighted")},s.prototype.destroy=function(){this.$results.remove()},s.prototype.ensureHighlightVisible=function(){var e,t,n,s,i=this.getHighlightedResults();0!==i.length&&(e=this.$results.find(".select2-results__option--selectable").index(i),s=this.$results.offset().top,t=i.offset().top,n=this.$results.scrollTop()+(t-s),s=t-s,n-=2*i.outerHeight(!1),e<=2?this.$results.scrollTop(0):(s>this.$results.outerHeight()||s<0)&&this.$results.scrollTop(n))},s.prototype.template=function(e,t){var n=this.options.get("templateResult"),s=this.options.get("escapeMarkup"),e=n(e,t);null==e?t.style.display="none":"string"==typeof e?t.innerHTML=s(e):d(t).append(e)},s}),u.define("select2/keys",[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),u.define("select2/selection/base",["jquery","../utils","../keys"],function(n,s,i){function r(e,t){this.$element=e,this.options=t,r.__super__.constructor.call(this)}return s.Extend(r,s.Observable),r.prototype.render=function(){var e=n('<span class="select2-selection" role="combobox" aria-haspopup="true" aria-expanded="false"></span>');return this._tabindex=0,null!=s.GetData(this.$element[0],"old-tabindex")?this._tabindex=s.GetData(this.$element[0],"old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),e.attr("title",this.$element.attr("title")),e.attr("tabindex",this._tabindex),e.attr("aria-disabled","false"),this.$selection=e},r.prototype.bind=function(e,t){var n=this,s=e.id+"-results";this.container=e,this.$selection.on("focus",function(e){n.trigger("focus",e)}),this.$selection.on("blur",function(e){n._handleBlur(e)}),this.$selection.on("keydown",function(e){n.trigger("keypress",e),e.which===i.SPACE&&e.preventDefault()}),e.on("results:focus",function(e){n.$selection.attr("aria-activedescendant",e.data._resultId)}),e.on("selection:update",function(e){n.update(e.data)}),e.on("open",function(){n.$selection.attr("aria-expanded","true"),n.$selection.attr("aria-owns",s),n._attachCloseHandler(e)}),e.on("close",function(){n.$selection.attr("aria-expanded","false"),n.$selection.removeAttr("aria-activedescendant"),n.$selection.removeAttr("aria-owns"),n.$selection.trigger("focus"),n._detachCloseHandler(e)}),e.on("enable",function(){n.$selection.attr("tabindex",n._tabindex),n.$selection.attr("aria-disabled","false")}),e.on("disable",function(){n.$selection.attr("tabindex","-1"),n.$selection.attr("aria-disabled","true")})},r.prototype._handleBlur=function(e){var t=this;window.setTimeout(function(){document.activeElement==t.$selection[0]||n.contains(t.$selection[0],document.activeElement)||t.trigger("blur",e)},1)},r.prototype._attachCloseHandler=function(e){n(document.body).on("mousedown.select2."+e.id,function(e){var t=n(e.target).closest(".select2");n(".select2.select2-container--open").each(function(){this!=t[0]&&s.GetData(this,"element").select2("close")})})},r.prototype._detachCloseHandler=function(e){n(document.body).off("mousedown.select2."+e.id)},r.prototype.position=function(e,t){t.find(".selection").append(e)},r.prototype.destroy=function(){this._detachCloseHandler(this.container)},r.prototype.update=function(e){throw new Error("The `update` method must be defined in child classes.")},r.prototype.isEnabled=function(){return!this.isDisabled()},r.prototype.isDisabled=function(){return this.options.get("disabled")},r}),u.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(e,t,n,s){function i(){i.__super__.constructor.apply(this,arguments)}return n.Extend(i,t),i.prototype.render=function(){var e=i.__super__.render.call(this);return e[0].classList.add("select2-selection--single"),e.html('<span class="select2-selection__rendered"></span><span class="select2-selection__arrow" role="presentation"><b role="presentation"></b></span>'),e},i.prototype.bind=function(t,e){var n=this;i.__super__.bind.apply(this,arguments);var s=t.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",s).attr("role","textbox").attr("aria-readonly","true"),this.$selection.attr("aria-labelledby",s),this.$selection.attr("aria-controls",s),this.$selection.on("mousedown",function(e){1===e.which&&n.trigger("toggle",{originalEvent:e})}),this.$selection.on("focus",function(e){}),this.$selection.on("blur",function(e){}),t.on("focus",function(e){t.isOpen()||n.$selection.trigger("focus")})},i.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},i.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},i.prototype.selectionContainer=function(){return e("<span></span>")},i.prototype.update=function(e){var t,n;0!==e.length?(n=e[0],t=this.$selection.find(".select2-selection__rendered"),e=this.display(n,t),t.empty().append(e),(n=n.title||n.text)?t.attr("title",n):t.removeAttr("title")):this.clear()},i}),u.define("select2/selection/multiple",["jquery","./base","../utils"],function(i,e,c){function r(e,t){r.__super__.constructor.apply(this,arguments)}return c.Extend(r,e),r.prototype.render=function(){var e=r.__super__.render.call(this);return e[0].classList.add("select2-selection--multiple"),e.html('<ul class="select2-selection__rendered"></ul>'),e},r.prototype.bind=function(e,t){var n=this;r.__super__.bind.apply(this,arguments);var s=e.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",s),this.$selection.on("click",function(e){n.trigger("toggle",{originalEvent:e})}),this.$selection.on("click",".select2-selection__choice__remove",function(e){var t;n.isDisabled()||(t=i(this).parent(),t=c.GetData(t[0],"data"),n.trigger("unselect",{originalEvent:e,data:t}))}),this.$selection.on("keydown",".select2-selection__choice__remove",function(e){n.isDisabled()||e.stopPropagation()})},r.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},r.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},r.prototype.selectionContainer=function(){return i('<li class="select2-selection__choice"><button type="button" class="select2-selection__choice__remove" tabindex="-1"><span aria-hidden="true">×</span></button><span class="select2-selection__choice__display"></span></li>')},r.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],n=this.$selection.find(".select2-selection__rendered").attr("id")+"-choice-",s=0;s<e.length;s++){var i=e[s],r=this.selectionContainer(),o=this.display(i,r),a=n+c.generateChars(4)+"-";i.id?a+=i.id:a+=c.generateChars(4),r.find(".select2-selection__choice__display").append(o).attr("id",a);var l=i.title||i.text;l&&r.attr("title",l);o=this.options.get("translations").get("removeItem"),l=r.find(".select2-selection__choice__remove");l.attr("title",o()),l.attr("aria-label",o()),l.attr("aria-describedby",a),c.StoreData(r[0],"data",i),t.push(r)}this.$selection.find(".select2-selection__rendered").append(t)}},r}),u.define("select2/selection/placeholder",[],function(){function e(e,t,n){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n)}return e.prototype.normalizePlaceholder=function(e,t){return t="string"==typeof t?{id:"",text:t}:t},e.prototype.createPlaceholder=function(e,t){var n=this.selectionContainer();n.html(this.display(t)),n[0].classList.add("select2-selection__placeholder"),n[0].classList.remove("select2-selection__choice");t=t.title||t.text||n.text();return this.$selection.find(".select2-selection__rendered").attr("title",t),n},e.prototype.update=function(e,t){var n=1==t.length&&t[0].id!=this.placeholder.id;if(1<t.length||n)return e.call(this,t);this.clear();t=this.createPlaceholder(this.placeholder);this.$selection.find(".select2-selection__rendered").append(t)},e}),u.define("select2/selection/allowClear",["jquery","../keys","../utils"],function(i,s,a){function e(){}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),null==this.placeholder&&this.options.get("debug")&&window.console&&console.error&&console.error("Select2: The `allowClear` option should be used in combination with the `placeholder` option."),this.$selection.on("mousedown",".select2-selection__clear",function(e){s._handleClear(e)}),t.on("keypress",function(e){s._handleKeyboardClear(e,t)})},e.prototype._handleClear=function(e,t){if(!this.isDisabled()){var n=this.$selection.find(".select2-selection__clear");if(0!==n.length){t.stopPropagation();var s=a.GetData(n[0],"data"),i=this.$element.val();this.$element.val(this.placeholder.id);var r={data:s};if(this.trigger("clear",r),r.prevented)this.$element.val(i);else{for(var o=0;o<s.length;o++)if(r={data:s[o]},this.trigger("unselect",r),r.prevented)return void this.$element.val(i);this.$element.trigger("input").trigger("change"),this.trigger("toggle",{})}}}},e.prototype._handleKeyboardClear=function(e,t,n){n.isOpen()||t.which!=s.DELETE&&t.which!=s.BACKSPACE||this._handleClear(t)},e.prototype.update=function(e,t){var n,s;e.call(this,t),this.$selection.find(".select2-selection__clear").remove(),this.$selection[0].classList.remove("select2-selection--clearable"),0<this.$selection.find(".select2-selection__placeholder").length||0===t.length||(n=this.$selection.find(".select2-selection__rendered").attr("id"),s=this.options.get("translations").get("removeAllItems"),(e=i('<button type="button" class="select2-selection__clear" tabindex="-1"><span aria-hidden="true">×</span></button>')).attr("title",s()),e.attr("aria-label",s()),e.attr("aria-describedby",n),a.StoreData(e[0],"data",t),this.$selection.prepend(e),this.$selection[0].classList.add("select2-selection--clearable"))},e}),u.define("select2/selection/search",["jquery","../utils","../keys"],function(s,a,l){function e(e,t,n){e.call(this,t,n)}return e.prototype.render=function(e){var t=this.options.get("translations").get("search"),n=s('<span class="select2-search select2-search--inline"><textarea class="select2-search__field" type="search" tabindex="-1" autocorrect="off" autocapitalize="none" spellcheck="false" role="searchbox" aria-autocomplete="list" ></textarea></span>');this.$searchContainer=n,this.$search=n.find("textarea"),this.$search.prop("autocomplete",this.options.get("autocomplete")),this.$search.attr("aria-label",t());e=e.call(this);return this._transferTabIndex(),e.append(this.$searchContainer),e},e.prototype.bind=function(e,t,n){var s=this,i=t.id+"-results",r=t.id+"-container";e.call(this,t,n),s.$search.attr("aria-describedby",r),t.on("open",function(){s.$search.attr("aria-controls",i),s.$search.trigger("focus")}),t.on("close",function(){s.$search.val(""),s.resizeSearch(),s.$search.removeAttr("aria-controls"),s.$search.removeAttr("aria-activedescendant"),s.$search.trigger("focus")}),t.on("enable",function(){s.$search.prop("disabled",!1),s._transferTabIndex()}),t.on("disable",function(){s.$search.prop("disabled",!0)}),t.on("focus",function(e){s.$search.trigger("focus")}),t.on("results:focus",function(e){e.data._resultId?s.$search.attr("aria-activedescendant",e.data._resultId):s.$search.removeAttr("aria-activedescendant")}),this.$selection.on("focusin",".select2-search--inline",function(e){s.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){s._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){var t;e.stopPropagation(),s.trigger("keypress",e),s._keyUpPrevented=e.isDefaultPrevented(),e.which!==l.BACKSPACE||""!==s.$search.val()||0<(t=s.$selection.find(".select2-selection__choice").last()).length&&(t=a.GetData(t[0],"data"),s.searchRemoveChoice(t),e.preventDefault())}),this.$selection.on("click",".select2-search--inline",function(e){s.$search.val()&&e.stopPropagation()});var t=document.documentMode,o=t&&t<=11;this.$selection.on("input.searchcheck",".select2-search--inline",function(e){o?s.$selection.off("input.search input.searchcheck"):s.$selection.off("keyup.search")}),this.$selection.on("keyup.search input.search",".select2-search--inline",function(e){var t;o&&"input"===e.type?s.$selection.off("input.search input.searchcheck"):(t=e.which)!=l.SHIFT&&t!=l.CTRL&&t!=l.ALT&&t!=l.TAB&&s.handleSearch(e)})},e.prototype._transferTabIndex=function(e){this.$search.attr("tabindex",this.$selection.attr("tabindex")),this.$selection.attr("tabindex","-1")},e.prototype.createPlaceholder=function(e,t){this.$search.attr("placeholder",t.text)},e.prototype.update=function(e,t){var n=this.$search[0]==document.activeElement;this.$search.attr("placeholder",""),e.call(this,t),this.resizeSearch(),n&&this.$search.trigger("focus")},e.prototype.handleSearch=function(){var e;this.resizeSearch(),this._keyUpPrevented||(e=this.$search.val(),this.trigger("query",{term:e})),this._keyUpPrevented=!1},e.prototype.searchRemoveChoice=function(e,t){this.trigger("unselect",{data:t}),this.$search.val(t.text),this.handleSearch()},e.prototype.resizeSearch=function(){this.$search.css("width","25px");var e="100%";""===this.$search.attr("placeholder")&&(e=.75*(this.$search.val().length+1)+"em"),this.$search.css("width",e)},e}),u.define("select2/selection/selectionCss",["../utils"],function(n){function e(){}return e.prototype.render=function(e){var t=e.call(this),e=this.options.get("selectionCssClass")||"";return-1!==e.indexOf(":all:")&&(e=e.replace(":all:",""),n.copyNonInternalCssClasses(t[0],this.$element[0])),t.addClass(e),t},e}),u.define("select2/selection/eventRelay",["jquery"],function(o){function e(){}return e.prototype.bind=function(e,t,n){var s=this,i=["open","opening","close","closing","select","selecting","unselect","unselecting","clear","clearing"],r=["opening","closing","selecting","unselecting","clearing"];e.call(this,t,n),t.on("*",function(e,t){var n;-1!==i.indexOf(e)&&(t=t||{},n=o.Event("select2:"+e,{params:t}),s.$element.trigger(n),-1!==r.indexOf(e)&&(t.prevented=n.isDefaultPrevented()))})},e}),u.define("select2/translation",["jquery","require"],function(t,n){function s(e){this.dict=e||{}}return s.prototype.all=function(){return this.dict},s.prototype.get=function(e){return this.dict[e]},s.prototype.extend=function(e){this.dict=t.extend({},e.all(),this.dict)},s._cache={},s.loadPath=function(e){var t;return e in s._cache||(t=n(e),s._cache[e]=t),new s(s._cache[e])},s}),u.define("select2/diacritics",[],function(){return{"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Œ":"OE","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","œ":"oe","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","Ό":"Ο","Ύ":"Υ","Ϋ":"Υ","Ώ":"Ω","ά":"α","έ":"ε","ή":"η","ί":"ι","ϊ":"ι","ΐ":"ι","ό":"ο","ύ":"υ","ϋ":"υ","ΰ":"υ","ώ":"ω","ς":"σ","’":"'"}}),u.define("select2/data/base",["../utils"],function(n){function s(e,t){s.__super__.constructor.call(this)}return n.Extend(s,n.Observable),s.prototype.current=function(e){throw new Error("The `current` method must be defined in child classes.")},s.prototype.query=function(e,t){throw new Error("The `query` method must be defined in child classes.")},s.prototype.bind=function(e,t){},s.prototype.destroy=function(){},s.prototype.generateResultId=function(e,t){e=e.id+"-result-";return e+=n.generateChars(4),null!=t.id?e+="-"+t.id.toString():e+="-"+n.generateChars(4),e},s}),u.define("select2/data/select",["./base","../utils","jquery"],function(e,a,l){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return a.Extend(n,e),n.prototype.current=function(e){var t=this;e(Array.prototype.map.call(this.$element[0].querySelectorAll(":checked"),function(e){return t.item(l(e))}))},n.prototype.select=function(i){var e,r=this;if(i.selected=!0,null!=i.element&&"option"===i.element.tagName.toLowerCase())return i.element.selected=!0,void this.$element.trigger("input").trigger("change");this.$element.prop("multiple")?this.current(function(e){var t=[];(i=[i]).push.apply(i,e);for(var n=0;n<i.length;n++){var s=i[n].id;-1===t.indexOf(s)&&t.push(s)}r.$element.val(t),r.$element.trigger("input").trigger("change")}):(e=i.id,this.$element.val(e),this.$element.trigger("input").trigger("change"))},n.prototype.unselect=function(i){var r=this;if(this.$element.prop("multiple")){if(i.selected=!1,null!=i.element&&"option"===i.element.tagName.toLowerCase())return i.element.selected=!1,void this.$element.trigger("input").trigger("change");this.current(function(e){for(var t=[],n=0;n<e.length;n++){var s=e[n].id;s!==i.id&&-1===t.indexOf(s)&&t.push(s)}r.$element.val(t),r.$element.trigger("input").trigger("change")})}},n.prototype.bind=function(e,t){var n=this;(this.container=e).on("select",function(e){n.select(e.data)}),e.on("unselect",function(e){n.unselect(e.data)})},n.prototype.destroy=function(){this.$element.find("*").each(function(){a.RemoveData(this)})},n.prototype.query=function(t,e){var n=[],s=this;this.$element.children().each(function(){var e;"option"!==this.tagName.toLowerCase()&&"optgroup"!==this.tagName.toLowerCase()||(e=l(this),e=s.item(e),null!==(e=s.matches(t,e))&&n.push(e))}),e({results:n})},n.prototype.addOptions=function(e){this.$element.append(e)},n.prototype.option=function(e){var t;e.children?(t=document.createElement("optgroup")).label=e.text:void 0!==(t=document.createElement("option")).textContent?t.textContent=e.text:t.innerText=e.text,void 0!==e.id&&(t.value=e.id),e.disabled&&(t.disabled=!0),e.selected&&(t.selected=!0),e.title&&(t.title=e.title);e=this._normalizeItem(e);return e.element=t,a.StoreData(t,"data",e),l(t)},n.prototype.item=function(e){var t={};if(null!=(t=a.GetData(e[0],"data")))return t;var n=e[0];if("option"===n.tagName.toLowerCase())t={id:e.val(),text:e.text(),disabled:e.prop("disabled"),selected:e.prop("selected"),title:e.prop("title")};else if("optgroup"===n.tagName.toLowerCase()){t={text:e.prop("label"),children:[],title:e.prop("title")};for(var s=e.children("option"),i=[],r=0;r<s.length;r++){var o=l(s[r]),o=this.item(o);i.push(o)}t.children=i}return(t=this._normalizeItem(t)).element=e[0],a.StoreData(e[0],"data",t),t},n.prototype._normalizeItem=function(e){e!==Object(e)&&(e={id:e,text:e});return null!=(e=l.extend({},{text:""},e)).id&&(e.id=e.id.toString()),null!=e.text&&(e.text=e.text.toString()),null==e._resultId&&e.id&&null!=this.container&&(e._resultId=this.generateResultId(this.container,e)),l.extend({},{selected:!1,disabled:!1},e)},n.prototype.matches=function(e,t){return this.options.get("matcher")(e,t)},n}),u.define("select2/data/array",["./select","../utils","jquery"],function(e,t,c){function s(e,t){this._dataToConvert=t.get("data")||[],s.__super__.constructor.call(this,e,t)}return t.Extend(s,e),s.prototype.bind=function(e,t){s.__super__.bind.call(this,e,t),this.addOptions(this.convertToOptions(this._dataToConvert))},s.prototype.select=function(n){var e=this.$element.find("option").filter(function(e,t){return t.value==n.id.toString()});0===e.length&&(e=this.option(n),this.addOptions(e)),s.__super__.select.call(this,n)},s.prototype.convertToOptions=function(e){var t=this,n=this.$element.find("option"),s=n.map(function(){return t.item(c(this)).id}).get(),i=[];for(var r=0;r<e.length;r++){var o,a,l=this._normalizeItem(e[r]);0<=s.indexOf(l.id)?(o=n.filter(function(e){return function(){return c(this).val()==e.id}}(l)),a=this.item(o),a=c.extend(!0,{},l,a),a=this.option(a),o.replaceWith(a)):(a=this.option(l),l.children&&(l=this.convertToOptions(l.children),a.append(l)),i.push(a))}return i},s}),u.define("select2/data/ajax",["./array","../utils","jquery"],function(e,t,r){function n(e,t){this.ajaxOptions=this._applyDefaults(t.get("ajax")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),n.__super__.constructor.call(this,e,t)}return t.Extend(n,e),n.prototype._applyDefaults=function(e){var t={data:function(e){return r.extend({},e,{q:e.term})},transport:function(e,t,n){e=r.ajax(e);return e.then(t),e.fail(n),e}};return r.extend({},t,e,!0)},n.prototype.processResults=function(e){return e},n.prototype.query=function(t,n){var s=this;null!=this._request&&("function"==typeof this._request.abort&&this._request.abort(),this._request=null);var i=r.extend({type:"GET"},this.ajaxOptions);function e(){var e=i.transport(i,function(e){e=s.processResults(e,t);s.options.get("debug")&&window.console&&console.error&&(e&&e.results&&Array.isArray(e.results)||console.error("Select2: The AJAX results did not return an array in the `results` key of the response.")),n(e)},function(){"status"in e&&(0===e.status||"0"===e.status)||s.trigger("results:message",{message:"errorLoading"})});s._request=e}"function"==typeof i.url&&(i.url=i.url.call(this.$element,t)),"function"==typeof i.data&&(i.data=i.data.call(this.$element,t)),this.ajaxOptions.delay&&null!=t.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(e,this.ajaxOptions.delay)):e()},n}),u.define("select2/data/tags",["jquery"],function(t){function e(e,t,n){var s=n.get("tags"),i=n.get("createTag");void 0!==i&&(this.createTag=i);i=n.get("insertTag");if(void 0!==i&&(this.insertTag=i),e.call(this,t,n),Array.isArray(s))for(var r=0;r<s.length;r++){var o=s[r],o=this._normalizeItem(o),o=this.option(o);this.$element.append(o)}}return e.prototype.query=function(e,c,u){var d=this;this._removeOldTags(),null!=c.term&&null==c.page?e.call(this,c,function e(t,n){for(var s=t.results,i=0;i<s.length;i++){var r=s[i],o=null!=r.children&&!e({results:r.children},!0);if((r.text||"").toUpperCase()===(c.term||"").toUpperCase()||o)return!n&&(t.data=s,void u(t))}if(n)return!0;var a,l=d.createTag(c);null!=l&&((a=d.option(l)).attr("data-select2-tag","true"),d.addOptions([a]),d.insertTag(s,l)),t.results=s,u(t)}):e.call(this,c,u)},e.prototype.createTag=function(e,t){if(null==t.term)return null;t=t.term.trim();return""===t?null:{id:t,text:t}},e.prototype.insertTag=function(e,t,n){t.unshift(n)},e.prototype._removeOldTags=function(e){this.$element.find("option[data-select2-tag]").each(function(){this.selected||t(this).remove()})},e}),u.define("select2/data/tokenizer",["jquery"],function(c){function e(e,t,n){var s=n.get("tokenizer");void 0!==s&&(this.tokenizer=s),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){e.call(this,t,n),this.$search=t.dropdown.$search||t.selection.$search||n.find(".select2-search__field")},e.prototype.query=function(e,t,n){var s=this;t.term=t.term||"";var i=this.tokenizer(t,this.options,function(e){var t,n=s._normalizeItem(e);s.$element.find("option").filter(function(){return c(this).val()===n.id}).length||((t=s.option(n)).attr("data-select2-tag",!0),s._removeOldTags(),s.addOptions([t])),t=n,s.trigger("select",{data:t})});i.term!==t.term&&(this.$search.length&&(this.$search.val(i.term),this.$search.trigger("focus")),t.term=i.term),e.call(this,t,n)},e.prototype.tokenizer=function(e,t,n,s){for(var i=n.get("tokenSeparators")||[],r=t.term,o=0,a=this.createTag||function(e){return{id:e.term,text:e.term}};o<r.length;){var l=r[o];-1!==i.indexOf(l)?(l=r.substr(0,o),null!=(l=a(c.extend({},t,{term:l})))?(s(l),r=r.substr(o+1)||"",o=0):o++):o++}return{term:r}},e}),u.define("select2/data/minimumInputLength",[],function(){function e(e,t,n){this.minimumInputLength=n.get("minimumInputLength"),e.call(this,t,n)}return e.prototype.query=function(e,t,n){t.term=t.term||"",t.term.length<this.minimumInputLength?this.trigger("results:message",{message:"inputTooShort",args:{minimum:this.minimumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),u.define("select2/data/maximumInputLength",[],function(){function e(e,t,n){this.maximumInputLength=n.get("maximumInputLength"),e.call(this,t,n)}return e.prototype.query=function(e,t,n){t.term=t.term||"",0<this.maximumInputLength&&t.term.length>this.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),u.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("select",function(){s._checkIfMaximumSelected()})},e.prototype.query=function(e,t,n){var s=this;this._checkIfMaximumSelected(function(){e.call(s,t,n)})},e.prototype._checkIfMaximumSelected=function(e,t){var n=this;this.current(function(e){e=null!=e?e.length:0;0<n.maximumSelectionLength&&e>=n.maximumSelectionLength?n.trigger("results:message",{message:"maximumSelected",args:{maximum:n.maximumSelectionLength}}):t&&t()})},e}),u.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('<span class="select2-dropdown"><span class="select2-results"></span></span>');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),u.define("select2/dropdown/search",["jquery"],function(r){function e(){}return e.prototype.render=function(e){var t=e.call(this),n=this.options.get("translations").get("search"),e=r('<span class="select2-search select2-search--dropdown"><input class="select2-search__field" type="search" tabindex="-1" autocorrect="off" autocapitalize="none" spellcheck="false" role="searchbox" aria-autocomplete="list" /></span>');return this.$searchContainer=e,this.$search=e.find("input"),this.$search.prop("autocomplete",this.options.get("autocomplete")),this.$search.attr("aria-label",n()),t.prepend(e),t},e.prototype.bind=function(e,t,n){var s=this,i=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){s.trigger("keypress",e),s._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){r(this).off("keyup")}),this.$search.on("keyup input",function(e){s.handleSearch(e)}),t.on("open",function(){s.$search.attr("tabindex",0),s.$search.attr("aria-controls",i),s.$search.trigger("focus"),window.setTimeout(function(){s.$search.trigger("focus")},0)}),t.on("close",function(){s.$search.attr("tabindex",-1),s.$search.removeAttr("aria-controls"),s.$search.removeAttr("aria-activedescendant"),s.$search.val(""),s.$search.trigger("blur")}),t.on("focus",function(){t.isOpen()||s.$search.trigger("focus")}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(s.showSearch(e)?s.$searchContainer[0].classList.remove("select2-search--hide"):s.$searchContainer[0].classList.add("select2-search--hide"))}),t.on("results:focus",function(e){e.data._resultId?s.$search.attr("aria-activedescendant",e.data._resultId):s.$search.removeAttr("aria-activedescendant")})},e.prototype.handleSearch=function(e){var t;this._keyUpPrevented||(t=this.$search.val(),this.trigger("query",{term:t})),this._keyUpPrevented=!1},e.prototype.showSearch=function(e,t){return!0},e}),u.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,s){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,s)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return t="string"==typeof t?{id:"",text:t}:t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),s=t.length-1;0<=s;s--){var i=t[s];this.placeholder.id===i.id&&n.splice(s,1)}return n},e}),u.define("select2/dropdown/infiniteScroll",["jquery"],function(n){function e(e,t,n,s){this.lastParams={},e.call(this,t,n,s),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&(this.$results.append(this.$loadingMore),this.loadMoreIfNeeded())},e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("query",function(e){s.lastParams=e,s.loading=!0}),t.on("query:append",function(e){s.lastParams=e,s.loading=!0}),this.$results.on("scroll",this.loadMoreIfNeeded.bind(this))},e.prototype.loadMoreIfNeeded=function(){var e=n.contains(document.documentElement,this.$loadingMore[0]);!this.loading&&e&&(e=this.$results.offset().top+this.$results.outerHeight(!1),this.$loadingMore.offset().top+this.$loadingMore.outerHeight(!1)<=e+50&&this.loadMore())},e.prototype.loadMore=function(){this.loading=!0;var e=n.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=n('<li class="select2-results__option select2-results__option--load-more"role="option" aria-disabled="true"></li>'),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),u.define("select2/dropdown/attachBody",["jquery","../utils"],function(u,o){function e(e,t,n){this.$dropdownParent=u(n.get("dropdownParent")||document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("open",function(){s._showDropdown(),s._attachPositioningHandler(t),s._bindContainerResultHandlers(t)}),t.on("close",function(){s._hideDropdown(),s._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t[0].classList.remove("select2"),t[0].classList.add("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=u("<span></span>"),e=e.call(this);return t.append(e),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._bindContainerResultHandlers=function(e,t){var n;this._containerResultsHandlersBound||(n=this,t.on("results:all",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:append",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:message",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("select",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("unselect",function(){n._positionDropdown(),n._resizeDropdown()}),this._containerResultsHandlersBound=!0)},e.prototype._attachPositioningHandler=function(e,t){var n=this,s="scroll.select2."+t.id,i="resize.select2."+t.id,r="orientationchange.select2."+t.id,t=this.$container.parents().filter(o.hasScroll);t.each(function(){o.StoreData(this,"select2-scroll-position",{x:u(this).scrollLeft(),y:u(this).scrollTop()})}),t.on(s,function(e){var t=o.GetData(this,"select2-scroll-position");u(this).scrollTop(t.y)}),u(window).on(s+" "+i+" "+r,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,s="resize.select2."+t.id,t="orientationchange.select2."+t.id;this.$container.parents().filter(o.hasScroll).off(n),u(window).off(n+" "+s+" "+t)},e.prototype._positionDropdown=function(){var e=u(window),t=this.$dropdown[0].classList.contains("select2-dropdown--above"),n=this.$dropdown[0].classList.contains("select2-dropdown--below"),s=null,i=this.$container.offset();i.bottom=i.top+this.$container.outerHeight(!1);var r={height:this.$container.outerHeight(!1)};r.top=i.top,r.bottom=i.top+r.height;var o=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=a<i.top-o,e=l>i.bottom+o,a={left:i.left,top:r.bottom},l=this.$dropdownParent;"static"===l.css("position")&&(l=l.offsetParent());i={top:0,left:0};(u.contains(document.body,l[0])||l[0].isConnected)&&(i=l.offset()),a.top-=i.top,a.left-=i.left,t||n||(s="below"),e||!c||t?!c&&e&&t&&(s="below"):s="above",("above"==s||t&&"below"!==s)&&(a.top=r.top-i.top-o),null!=s&&(this.$dropdown[0].classList.remove("select2-dropdown--below"),this.$dropdown[0].classList.remove("select2-dropdown--above"),this.$dropdown[0].classList.add("select2-dropdown--"+s),this.$container[0].classList.remove("select2-container--below"),this.$container[0].classList.remove("select2-container--above"),this.$container[0].classList.add("select2-container--"+s)),this.$dropdownContainer.css(a)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),u.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,s){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=1/0),e.call(this,t,n,s)}return e.prototype.showSearch=function(e,t){return!(function e(t){for(var n=0,s=0;s<t.length;s++){var i=t[s];i.children?n+=e(i.children):n++}return n}(t.data.results)<this.minimumResultsForSearch)&&e.call(this,t)},e}),u.define("select2/dropdown/selectOnClose",["../utils"],function(s){function e(){}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("close",function(e){s._handleSelectOnClose(e)})},e.prototype._handleSelectOnClose=function(e,t){if(t&&null!=t.originalSelect2Event){var n=t.originalSelect2Event;if("select"===n._type||"unselect"===n._type)return}n=this.getHighlightedResults();n.length<1||(null!=(n=s.GetData(n[0],"data")).element&&n.element.selected||null==n.element&&n.selected||this.trigger("select",{data:n}))},e}),u.define("select2/dropdown/closeOnSelect",[],function(){function e(){}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("select",function(e){s._selectTriggered(e)}),t.on("unselect",function(e){s._selectTriggered(e)})},e.prototype._selectTriggered=function(e,t){var n=t.originalEvent;n&&(n.ctrlKey||n.metaKey)||this.trigger("close",{originalEvent:n,originalSelect2Event:t})},e}),u.define("select2/dropdown/dropdownCss",["../utils"],function(n){function e(){}return e.prototype.render=function(e){var t=e.call(this),e=this.options.get("dropdownCssClass")||"";return-1!==e.indexOf(":all:")&&(e=e.replace(":all:",""),n.copyNonInternalCssClasses(t[0],this.$element[0])),t.addClass(e),t},e}),u.define("select2/dropdown/tagsSearchHighlight",["../utils"],function(s){function e(){}return e.prototype.highlightFirstItem=function(e){var t=this.$results.find(".select2-results__option--selectable:not(.select2-results__option--selected)");if(0<t.length){var n=t.first(),t=s.GetData(n[0],"data").element;if(t&&t.getAttribute&&"true"===t.getAttribute("data-select2-tag"))return void n.trigger("mouseenter")}e.call(this)},e}),u.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var t=e.input.length-e.maximum,e="Please delete "+t+" character";return 1!=t&&(e+="s"),e},inputTooShort:function(e){return"Please enter "+(e.minimum-e.input.length)+" or more characters"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var t="You can only select "+e.maximum+" item";return 1!=e.maximum&&(t+="s"),t},noResults:function(){return"No results found"},searching:function(){return"Searching…"},removeAllItems:function(){return"Remove all items"},removeItem:function(){return"Remove item"},search:function(){return"Search"}}}),u.define("select2/defaults",["jquery","./results","./selection/single","./selection/multiple","./selection/placeholder","./selection/allowClear","./selection/search","./selection/selectionCss","./selection/eventRelay","./utils","./translation","./diacritics","./data/select","./data/array","./data/ajax","./data/tags","./data/tokenizer","./data/minimumInputLength","./data/maximumInputLength","./data/maximumSelectionLength","./dropdown","./dropdown/search","./dropdown/hidePlaceholder","./dropdown/infiniteScroll","./dropdown/attachBody","./dropdown/minimumResultsForSearch","./dropdown/selectOnClose","./dropdown/closeOnSelect","./dropdown/dropdownCss","./dropdown/tagsSearchHighlight","./i18n/en"],function(l,r,o,a,c,u,d,p,h,f,g,t,m,y,v,_,b,$,w,x,A,D,S,E,O,C,L,T,q,I,e){function n(){this.reset()}return n.prototype.apply=function(e){var t;null==(e=l.extend(!0,{},this.defaults,e)).dataAdapter&&(null!=e.ajax?e.dataAdapter=v:null!=e.data?e.dataAdapter=y:e.dataAdapter=m,0<e.minimumInputLength&&(e.dataAdapter=f.Decorate(e.dataAdapter,$)),0<e.maximumInputLength&&(e.dataAdapter=f.Decorate(e.dataAdapter,w)),0<e.maximumSelectionLength&&(e.dataAdapter=f.Decorate(e.dataAdapter,x)),e.tags&&(e.dataAdapter=f.Decorate(e.dataAdapter,_)),null==e.tokenSeparators&&null==e.tokenizer||(e.dataAdapter=f.Decorate(e.dataAdapter,b))),null==e.resultsAdapter&&(e.resultsAdapter=r,null!=e.ajax&&(e.resultsAdapter=f.Decorate(e.resultsAdapter,E)),null!=e.placeholder&&(e.resultsAdapter=f.Decorate(e.resultsAdapter,S)),e.selectOnClose&&(e.resultsAdapter=f.Decorate(e.resultsAdapter,L)),e.tags&&(e.resultsAdapter=f.Decorate(e.resultsAdapter,I))),null==e.dropdownAdapter&&(e.multiple?e.dropdownAdapter=A:(t=f.Decorate(A,D),e.dropdownAdapter=t),0!==e.minimumResultsForSearch&&(e.dropdownAdapter=f.Decorate(e.dropdownAdapter,C)),e.closeOnSelect&&(e.dropdownAdapter=f.Decorate(e.dropdownAdapter,T)),null!=e.dropdownCssClass&&(e.dropdownAdapter=f.Decorate(e.dropdownAdapter,q)),e.dropdownAdapter=f.Decorate(e.dropdownAdapter,O)),null==e.selectionAdapter&&(e.multiple?e.selectionAdapter=a:e.selectionAdapter=o,null!=e.placeholder&&(e.selectionAdapter=f.Decorate(e.selectionAdapter,c)),e.allowClear&&(e.selectionAdapter=f.Decorate(e.selectionAdapter,u)),e.multiple&&(e.selectionAdapter=f.Decorate(e.selectionAdapter,d)),null!=e.selectionCssClass&&(e.selectionAdapter=f.Decorate(e.selectionAdapter,p)),e.selectionAdapter=f.Decorate(e.selectionAdapter,h)),e.language=this._resolveLanguage(e.language),e.language.push("en");for(var n=[],s=0;s<e.language.length;s++){var i=e.language[s];-1===n.indexOf(i)&&n.push(i)}return e.language=n,e.translations=this._processTranslations(e.language,e.debug),e},n.prototype.reset=function(){function a(e){return e.replace(/[^\u0000-\u007E]/g,function(e){return t[e]||e})}this.defaults={amdLanguageBase:"./i18n/",autocomplete:"off",closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:f.escapeMarkup,language:{},matcher:function e(t,n){if(null==t.term||""===t.term.trim())return n;if(n.children&&0<n.children.length){for(var s=l.extend(!0,{},n),i=n.children.length-1;0<=i;i--)null==e(t,n.children[i])&&s.children.splice(i,1);return 0<s.children.length?s:e(t,s)}var r=a(n.text).toUpperCase(),o=a(t.term).toUpperCase();return-1<r.indexOf(o)?n:null},minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,scrollAfterSelect:!1,sorter:function(e){return e},templateResult:function(e){return e.text},templateSelection:function(e){return e.text},theme:"default",width:"resolve"}},n.prototype.applyFromElement=function(e,t){var n=e.language,s=this.defaults.language,i=t.prop("lang"),t=t.closest("[lang]").prop("lang"),t=Array.prototype.concat.call(this._resolveLanguage(i),this._resolveLanguage(n),this._resolveLanguage(s),this._resolveLanguage(t));return e.language=t,e},n.prototype._resolveLanguage=function(e){if(!e)return[];if(l.isEmptyObject(e))return[];if(l.isPlainObject(e))return[e];for(var t,n=Array.isArray(e)?e:[e],s=[],i=0;i<n.length;i++)s.push(n[i]),"string"==typeof n[i]&&0<n[i].indexOf("-")&&(t=n[i].split("-")[0],s.push(t));return s},n.prototype._processTranslations=function(e,t){for(var n=new g,s=0;s<e.length;s++){var i=new g,r=e[s];if("string"==typeof r)try{i=g.loadPath(r)}catch(e){try{r=this.defaults.amdLanguageBase+r,i=g.loadPath(r)}catch(e){t&&window.console&&console.warn&&console.warn('Select2: The language file for "'+r+'" could not be automatically loaded. A fallback will be used instead.')}}else i=l.isPlainObject(r)?new g(r):r;n.extend(i)}return n},n.prototype.set=function(e,t){var n={};n[l.camelCase(e)]=t;n=f._convertData(n);l.extend(!0,this.defaults,n)},new n}),u.define("select2/options",["jquery","./defaults","./utils"],function(c,n,u){function e(e,t){this.options=e,null!=t&&this.fromElement(t),null!=t&&(this.options=n.applyFromElement(this.options,t)),this.options=n.apply(this.options)}return e.prototype.fromElement=function(e){var t=["select2"];null==this.options.multiple&&(this.options.multiple=e.prop("multiple")),null==this.options.disabled&&(this.options.disabled=e.prop("disabled")),null==this.options.autocomplete&&e.prop("autocomplete")&&(this.options.autocomplete=e.prop("autocomplete")),null==this.options.dir&&(e.prop("dir")?this.options.dir=e.prop("dir"):e.closest("[dir]").prop("dir")?this.options.dir=e.closest("[dir]").prop("dir"):this.options.dir="ltr"),e.prop("disabled",this.options.disabled),e.prop("multiple",this.options.multiple),u.GetData(e[0],"select2Tags")&&(this.options.debug&&window.console&&console.warn&&console.warn('Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags="true"` attributes and will be removed in future versions of Select2.'),u.StoreData(e[0],"data",u.GetData(e[0],"select2Tags")),u.StoreData(e[0],"tags",!0)),u.GetData(e[0],"ajaxUrl")&&(this.options.debug&&window.console&&console.warn&&console.warn("Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2."),e.attr("ajax--url",u.GetData(e[0],"ajaxUrl")),u.StoreData(e[0],"ajax-Url",u.GetData(e[0],"ajaxUrl")));var n={};function s(e,t){return t.toUpperCase()}for(var i=0;i<e[0].attributes.length;i++){var r=e[0].attributes[i].name,o="data-";r.substr(0,o.length)==o&&(r=r.substring(o.length),o=u.GetData(e[0],r),n[r.replace(/-([a-z])/g,s)]=o)}c.fn.jquery&&"1."==c.fn.jquery.substr(0,2)&&e[0].dataset&&(n=c.extend(!0,{},e[0].dataset,n));var a,l=c.extend(!0,{},u.GetData(e[0]),n);for(a in l=u._convertData(l))-1<t.indexOf(a)||(c.isPlainObject(this.options[a])?c.extend(this.options[a],l[a]):this.options[a]=l[a]);return this},e.prototype.get=function(e){return this.options[e]},e.prototype.set=function(e,t){this.options[e]=t},e}),u.define("select2/core",["jquery","./options","./utils","./keys"],function(t,i,r,s){var o=function(e,t){null!=r.GetData(e[0],"select2")&&r.GetData(e[0],"select2").destroy(),this.$element=e,this.id=this._generateId(e),t=t||{},this.options=new i(t,e),o.__super__.constructor.call(this);var n=e.attr("tabindex")||0;r.StoreData(e[0],"old-tabindex",n),e.attr("tabindex","-1");t=this.options.get("dataAdapter");this.dataAdapter=new t(e,this.options);n=this.render();this._placeContainer(n);t=this.options.get("selectionAdapter");this.selection=new t(e,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,n);t=this.options.get("dropdownAdapter");this.dropdown=new t(e,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,n);n=this.options.get("resultsAdapter");this.results=new n(e,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var s=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(e){s.trigger("selection:update",{data:e})}),e[0].classList.add("select2-hidden-accessible"),e.attr("aria-hidden","true"),this._syncAttributes(),r.StoreData(e[0],"select2",this),e.data("select2",this)};return r.Extend(o,r.Observable),o.prototype._generateId=function(e){return"select2-"+(null!=e.attr("id")?e.attr("id"):null!=e.attr("name")?e.attr("name")+"-"+r.generateChars(2):r.generateChars(4)).replace(/(:|\.|\[|\]|,)/g,"")},o.prototype._placeContainer=function(e){e.insertAfter(this.$element);var t=this._resolveWidth(this.$element,this.options.get("width"));null!=t&&e.css("width",t)},o.prototype._resolveWidth=function(e,t){var n=/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if("resolve"==t){var s=this._resolveWidth(e,"style");return null!=s?s:this._resolveWidth(e,"element")}if("element"==t){s=e.outerWidth(!1);return s<=0?"auto":s+"px"}if("style"!=t)return"computedstyle"!=t?t:window.getComputedStyle(e[0]).width;e=e.attr("style");if("string"!=typeof e)return null;for(var i=e.split(";"),r=0,o=i.length;r<o;r+=1){var a=i[r].replace(/\s/g,"").match(n);if(null!==a&&1<=a.length)return a[1]}return null},o.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},o.prototype._registerDomEvents=function(){var t=this;this.$element.on("change.select2",function(){t.dataAdapter.current(function(e){t.trigger("selection:update",{data:e})})}),this.$element.on("focus.select2",function(e){t.trigger("focus",e)}),this._syncA=r.bind(this._syncAttributes,this),this._syncS=r.bind(this._syncSubtree,this),this._observer=new window.MutationObserver(function(e){t._syncA(),t._syncS(e)}),this._observer.observe(this.$element[0],{attributes:!0,childList:!0,subtree:!1})},o.prototype._registerDataEvents=function(){var n=this;this.dataAdapter.on("*",function(e,t){n.trigger(e,t)})},o.prototype._registerSelectionEvents=function(){var n=this,s=["toggle","focus"];this.selection.on("toggle",function(){n.toggleDropdown()}),this.selection.on("focus",function(e){n.focus(e)}),this.selection.on("*",function(e,t){-1===s.indexOf(e)&&n.trigger(e,t)})},o.prototype._registerDropdownEvents=function(){var n=this;this.dropdown.on("*",function(e,t){n.trigger(e,t)})},o.prototype._registerResultsEvents=function(){var n=this;this.results.on("*",function(e,t){n.trigger(e,t)})},o.prototype._registerEvents=function(){var n=this;this.on("open",function(){n.$container[0].classList.add("select2-container--open")}),this.on("close",function(){n.$container[0].classList.remove("select2-container--open")}),this.on("enable",function(){n.$container[0].classList.remove("select2-container--disabled")}),this.on("disable",function(){n.$container[0].classList.add("select2-container--disabled")}),this.on("blur",function(){n.$container[0].classList.remove("select2-container--focus")}),this.on("query",function(t){n.isOpen()||n.trigger("open",{}),this.dataAdapter.query(t,function(e){n.trigger("results:all",{data:e,query:t})})}),this.on("query:append",function(t){this.dataAdapter.query(t,function(e){n.trigger("results:append",{data:e,query:t})})}),this.on("keypress",function(e){var t=e.which;n.isOpen()?t===s.ESC||t===s.UP&&e.altKey?(n.close(e),e.preventDefault()):t===s.ENTER||t===s.TAB?(n.trigger("results:select",{}),e.preventDefault()):t===s.SPACE&&e.ctrlKey?(n.trigger("results:toggle",{}),e.preventDefault()):t===s.UP?(n.trigger("results:previous",{}),e.preventDefault()):t===s.DOWN&&(n.trigger("results:next",{}),e.preventDefault()):(t===s.ENTER||t===s.SPACE||t===s.DOWN&&e.altKey)&&(n.open(),e.preventDefault())})},o.prototype._syncAttributes=function(){this.options.set("disabled",this.$element.prop("disabled")),this.isDisabled()?(this.isOpen()&&this.close(),this.trigger("disable",{})):this.trigger("enable",{})},o.prototype._isChangeMutation=function(e){var t=this;if(e.addedNodes&&0<e.addedNodes.length){for(var n=0;n<e.addedNodes.length;n++)if(e.addedNodes[n].selected)return!0}else{if(e.removedNodes&&0<e.removedNodes.length)return!0;if(Array.isArray(e))return e.some(function(e){return t._isChangeMutation(e)})}return!1},o.prototype._syncSubtree=function(e){var e=this._isChangeMutation(e),t=this;e&&this.dataAdapter.current(function(e){t.trigger("selection:update",{data:e})})},o.prototype.trigger=function(e,t){var n=o.__super__.trigger,s={open:"opening",close:"closing",select:"selecting",unselect:"unselecting",clear:"clearing"};if(void 0===t&&(t={}),e in s){var i=s[e],s={prevented:!1,name:e,args:t};if(n.call(this,i,s),s.prevented)return void(t.prevented=!0)}n.call(this,e,t)},o.prototype.toggleDropdown=function(){this.isDisabled()||(this.isOpen()?this.close():this.open())},o.prototype.open=function(){this.isOpen()||this.isDisabled()||this.trigger("query",{})},o.prototype.close=function(e){this.isOpen()&&this.trigger("close",{originalEvent:e})},o.prototype.isEnabled=function(){return!this.isDisabled()},o.prototype.isDisabled=function(){return this.options.get("disabled")},o.prototype.isOpen=function(){return this.$container[0].classList.contains("select2-container--open")},o.prototype.hasFocus=function(){return this.$container[0].classList.contains("select2-container--focus")},o.prototype.focus=function(e){this.hasFocus()||(this.$container[0].classList.add("select2-container--focus"),this.trigger("focus",{}))},o.prototype.enable=function(e){this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("enable")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop("disabled") instead.');e=!(e=null==e||0===e.length?[!0]:e)[0];this.$element.prop("disabled",e)},o.prototype.data=function(){this.options.get("debug")&&0<arguments.length&&window.console&&console.warn&&console.warn('Select2: Data can no longer be set using `select2("data")`. You should consider setting the value instead using `$element.val()`.');var t=[];return this.dataAdapter.current(function(e){t=e}),t},o.prototype.val=function(e){if(this.options.get("debug")&&window.console&&console.warn&&console.warn('Select2: The `select2("val")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.'),null==e||0===e.length)return this.$element.val();e=e[0];Array.isArray(e)&&(e=e.map(function(e){return e.toString()})),this.$element.val(e).trigger("input").trigger("change")},o.prototype.destroy=function(){r.RemoveData(this.$container[0]),this.$container.remove(),this._observer.disconnect(),this._observer=null,this._syncA=null,this._syncS=null,this.$element.off(".select2"),this.$element.attr("tabindex",r.GetData(this.$element[0],"old-tabindex")),this.$element[0].classList.remove("select2-hidden-accessible"),this.$element.attr("aria-hidden","false"),r.RemoveData(this.$element[0]),this.$element.removeData("select2"),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null},o.prototype.render=function(){var e=t('<span class="select2 select2-container"><span class="selection"></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container[0].classList.add("select2-container--"+this.options.get("theme")),r.StoreData(e[0],"element",this.$element),e},o}),u.define("jquery-mousewheel",["jquery"],function(e){return e}),u.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults","./select2/utils"],function(i,e,r,t,o){var a;return null==i.fn.select2&&(a=["open","close","destroy"],i.fn.select2=function(t){if("object"==typeof(t=t||{}))return this.each(function(){var e=i.extend(!0,{},t);new r(i(this),e)}),this;if("string"!=typeof t)throw new Error("Invalid arguments for Select2: "+t);var n,s=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=o.GetData(this,"select2");null==e&&window.console&&console.error&&console.error("The select2('"+t+"') method was called on an element that is not using Select2."),n=e[t].apply(e,s)}),-1<a.indexOf(t)?this:n}),null==i.fn.select2.defaults&&(i.fn.select2.defaults=t),r}),{define:u.define,require:u.require});function b(e,t){return i.call(e,t)}function l(e,t){var n,s,i,r,o,a,l,c,u,d,p=t&&t.split("/"),h=y.map,f=h&&h["*"]||{};if(e){for(t=(e=e.split("/")).length-1,y.nodeIdCompat&&_.test(e[t])&&(e[t]=e[t].replace(_,"")),"."===e[0].charAt(0)&&p&&(e=p.slice(0,p.length-1).concat(e)),c=0;c<e.length;c++)"."===(d=e[c])?(e.splice(c,1),--c):".."===d&&(0===c||1===c&&".."===e[2]||".."===e[c-1]||0<c&&(e.splice(c-1,2),c-=2));e=e.join("/")}if((p||f)&&h){for(c=(n=e.split("/")).length;0<c;--c){if(s=n.slice(0,c).join("/"),p)for(u=p.length;0<u;--u)if(i=h[p.slice(0,u).join("/")],i=i&&i[s]){r=i,o=c;break}if(r)break;!a&&f&&f[s]&&(a=f[s],l=c)}!r&&a&&(r=a,o=l),r&&(n.splice(0,o,r),e=n.join("/"))}return e}function w(t,n){return function(){var e=a.call(arguments,0);return"string"!=typeof e[0]&&1===e.length&&e.push(null),o.apply(p,e.concat([t,n]))}}function x(e){var t;if(b(m,e)&&(t=m[e],delete m[e],v[e]=!0,r.apply(p,t)),!b(g,e)&&!b(v,e))throw new Error("No "+e);return g[e]}function c(e){var t,n=e?e.indexOf("!"):-1;return-1<n&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function A(e){return e?c(e):[]}var u=s.require("jquery.select2");return t.fn.select2.amd=s,u}); +!function(t,s){"object"==typeof exports&&"undefined"!=typeof module?module.exports=s():"function"==typeof define&&define.amd?define(s):(t||self).Typed=s()}(this,function(){function t(){return t=Object.assign?Object.assign.bind():function(t){for(var s=1;s<arguments.length;s++){var e=arguments[s];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}return t},t.apply(this,arguments)}var s={strings:["These are the default values...","You know what you should do?","Use your own!","Have a great day!"],stringsElement:null,typeSpeed:0,startDelay:0,backSpeed:0,smartBackspace:!0,shuffle:!1,backDelay:700,fadeOut:!1,fadeOutClass:"typed-fade-out",fadeOutDelay:500,loop:!1,loopCount:Infinity,showCursor:!0,cursorChar:"|",autoInsertCss:!0,attr:null,bindInputFocusEvents:!1,contentType:"html",onBegin:function(t){},onComplete:function(t){},preStringTyped:function(t,s){},onStringTyped:function(t,s){},onLastStringBackspaced:function(t){},onTypingPaused:function(t,s){},onTypingResumed:function(t,s){},onReset:function(t){},onStop:function(t,s){},onStart:function(t,s){},onDestroy:function(t){}},e=new(/*#__PURE__*/function(){function e(){}var n=e.prototype;return n.load=function(e,n,i){if(e.el="string"==typeof i?document.querySelector(i):i,e.options=t({},s,n),e.isInput="input"===e.el.tagName.toLowerCase(),e.attr=e.options.attr,e.bindInputFocusEvents=e.options.bindInputFocusEvents,e.showCursor=!e.isInput&&e.options.showCursor,e.cursorChar=e.options.cursorChar,e.cursorBlinking=!0,e.elContent=e.attr?e.el.getAttribute(e.attr):e.el.textContent,e.contentType=e.options.contentType,e.typeSpeed=e.options.typeSpeed,e.startDelay=e.options.startDelay,e.backSpeed=e.options.backSpeed,e.smartBackspace=e.options.smartBackspace,e.backDelay=e.options.backDelay,e.fadeOut=e.options.fadeOut,e.fadeOutClass=e.options.fadeOutClass,e.fadeOutDelay=e.options.fadeOutDelay,e.isPaused=!1,e.strings=e.options.strings.map(function(t){return t.trim()}),e.stringsElement="string"==typeof e.options.stringsElement?document.querySelector(e.options.stringsElement):e.options.stringsElement,e.stringsElement){e.strings=[],e.stringsElement.style.cssText="clip: rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px;";var r=Array.prototype.slice.apply(e.stringsElement.children),o=r.length;if(o)for(var a=0;a<o;a+=1)e.strings.push(r[a].innerHTML.trim())}for(var u in e.strPos=0,e.currentElContent=this.getCurrentElContent(e),e.currentElContent&&e.currentElContent.length>0&&(e.strPos=e.currentElContent.length-1,e.strings.unshift(e.currentElContent)),e.sequence=[],e.strings)e.sequence[u]=u;e.arrayPos=0,e.stopNum=0,e.loop=e.options.loop,e.loopCount=e.options.loopCount,e.curLoop=0,e.shuffle=e.options.shuffle,e.pause={status:!1,typewrite:!0,curString:"",curStrPos:0},e.typingComplete=!1,e.autoInsertCss=e.options.autoInsertCss,e.autoInsertCss&&(this.appendCursorAnimationCss(e),this.appendFadeOutAnimationCss(e))},n.getCurrentElContent=function(t){return t.attr?t.el.getAttribute(t.attr):t.isInput?t.el.value:"html"===t.contentType?t.el.innerHTML:t.el.textContent},n.appendCursorAnimationCss=function(t){var s="data-typed-js-cursor-css";if(t.showCursor&&!document.querySelector("["+s+"]")){var e=document.createElement("style");e.setAttribute(s,"true"),e.innerHTML="\n .typed-cursor{\n opacity: 1;\n }\n .typed-cursor.typed-cursor--blink{\n animation: typedjsBlink 0.7s infinite;\n -webkit-animation: typedjsBlink 0.7s infinite;\n animation: typedjsBlink 0.7s infinite;\n }\n @keyframes typedjsBlink{\n 50% { opacity: 0.0; }\n }\n @-webkit-keyframes typedjsBlink{\n 0% { opacity: 1; }\n 50% { opacity: 0.0; }\n 100% { opacity: 1; }\n }\n ",document.body.appendChild(e)}},n.appendFadeOutAnimationCss=function(t){var s="data-typed-fadeout-js-css";if(t.fadeOut&&!document.querySelector("["+s+"]")){var e=document.createElement("style");e.setAttribute(s,"true"),e.innerHTML="\n .typed-fade-out{\n opacity: 0;\n transition: opacity .25s;\n }\n .typed-cursor.typed-cursor--blink.typed-fade-out{\n -webkit-animation: 0;\n animation: 0;\n }\n ",document.body.appendChild(e)}},e}()),n=new(/*#__PURE__*/function(){function t(){}var s=t.prototype;return s.typeHtmlChars=function(t,s,e){if("html"!==e.contentType)return s;var n=t.substring(s).charAt(0);if("<"===n||"&"===n){var i;for(i="<"===n?">":";";t.substring(s+1).charAt(0)!==i&&!(1+ ++s>t.length););s++}return s},s.backSpaceHtmlChars=function(t,s,e){if("html"!==e.contentType)return s;var n=t.substring(s).charAt(0);if(">"===n||";"===n){var i;for(i=">"===n?"<":"&";t.substring(s-1).charAt(0)!==i&&!(--s<0););s--}return s},t}());/*#__PURE__*/ +return function(){function t(t,s){e.load(this,s,t),this.begin()}var s=t.prototype;return s.toggle=function(){this.pause.status?this.start():this.stop()},s.stop=function(){this.typingComplete||this.pause.status||(this.toggleBlinking(!0),this.pause.status=!0,this.options.onStop(this.arrayPos,this))},s.start=function(){this.typingComplete||this.pause.status&&(this.pause.status=!1,this.pause.typewrite?this.typewrite(this.pause.curString,this.pause.curStrPos):this.backspace(this.pause.curString,this.pause.curStrPos),this.options.onStart(this.arrayPos,this))},s.destroy=function(){this.reset(!1),this.options.onDestroy(this)},s.reset=function(t){void 0===t&&(t=!0),clearInterval(this.timeout),this.replaceText(""),this.cursor&&this.cursor.parentNode&&(this.cursor.parentNode.removeChild(this.cursor),this.cursor=null),this.strPos=0,this.arrayPos=0,this.curLoop=0,t&&(this.insertCursor(),this.options.onReset(this),this.begin())},s.begin=function(){var t=this;this.options.onBegin(this),this.typingComplete=!1,this.shuffleStringsIfNeeded(this),this.insertCursor(),this.bindInputFocusEvents&&this.bindFocusEvents(),this.timeout=setTimeout(function(){0===t.strPos?t.typewrite(t.strings[t.sequence[t.arrayPos]],t.strPos):t.backspace(t.strings[t.sequence[t.arrayPos]],t.strPos)},this.startDelay)},s.typewrite=function(t,s){var e=this;this.fadeOut&&this.el.classList.contains(this.fadeOutClass)&&(this.el.classList.remove(this.fadeOutClass),this.cursor&&this.cursor.classList.remove(this.fadeOutClass));var i=this.humanizer(this.typeSpeed),r=1;!0!==this.pause.status?this.timeout=setTimeout(function(){s=n.typeHtmlChars(t,s,e);var i=0,o=t.substring(s);if("^"===o.charAt(0)&&/^\^\d+/.test(o)){var a=1;a+=(o=/\d+/.exec(o)[0]).length,i=parseInt(o),e.temporaryPause=!0,e.options.onTypingPaused(e.arrayPos,e),t=t.substring(0,s)+t.substring(s+a),e.toggleBlinking(!0)}if("`"===o.charAt(0)){for(;"`"!==t.substring(s+r).charAt(0)&&(r++,!(s+r>t.length)););var u=t.substring(0,s),p=t.substring(u.length+1,s+r),c=t.substring(s+r+1);t=u+p+c,r--}e.timeout=setTimeout(function(){e.toggleBlinking(!1),s>=t.length?e.doneTyping(t,s):e.keepTyping(t,s,r),e.temporaryPause&&(e.temporaryPause=!1,e.options.onTypingResumed(e.arrayPos,e))},i)},i):this.setPauseStatus(t,s,!0)},s.keepTyping=function(t,s,e){0===s&&(this.toggleBlinking(!1),this.options.preStringTyped(this.arrayPos,this));var n=t.substring(0,s+=e);this.replaceText(n),this.typewrite(t,s)},s.doneTyping=function(t,s){var e=this;this.options.onStringTyped(this.arrayPos,this),this.toggleBlinking(!0),this.arrayPos===this.strings.length-1&&(this.complete(),!1===this.loop||this.curLoop===this.loopCount)||(this.timeout=setTimeout(function(){e.backspace(t,s)},this.backDelay))},s.backspace=function(t,s){var e=this;if(!0!==this.pause.status){if(this.fadeOut)return this.initFadeOut();this.toggleBlinking(!1);var i=this.humanizer(this.backSpeed);this.timeout=setTimeout(function(){s=n.backSpaceHtmlChars(t,s,e);var i=t.substring(0,s);if(e.replaceText(i),e.smartBackspace){var r=e.strings[e.arrayPos+1];e.stopNum=r&&i===r.substring(0,s)?s:0}s>e.stopNum?(s--,e.backspace(t,s)):s<=e.stopNum&&(e.arrayPos++,e.arrayPos===e.strings.length?(e.arrayPos=0,e.options.onLastStringBackspaced(),e.shuffleStringsIfNeeded(),e.begin()):e.typewrite(e.strings[e.sequence[e.arrayPos]],s))},i)}else this.setPauseStatus(t,s,!1)},s.complete=function(){this.options.onComplete(this),this.loop?this.curLoop++:this.typingComplete=!0},s.setPauseStatus=function(t,s,e){this.pause.typewrite=e,this.pause.curString=t,this.pause.curStrPos=s},s.toggleBlinking=function(t){this.cursor&&(this.pause.status||this.cursorBlinking!==t&&(this.cursorBlinking=t,t?this.cursor.classList.add("typed-cursor--blink"):this.cursor.classList.remove("typed-cursor--blink")))},s.humanizer=function(t){return Math.round(Math.random()*t/2)+t},s.shuffleStringsIfNeeded=function(){this.shuffle&&(this.sequence=this.sequence.sort(function(){return Math.random()-.5}))},s.initFadeOut=function(){var t=this;return this.el.className+=" "+this.fadeOutClass,this.cursor&&(this.cursor.className+=" "+this.fadeOutClass),setTimeout(function(){t.arrayPos++,t.replaceText(""),t.strings.length>t.arrayPos?t.typewrite(t.strings[t.sequence[t.arrayPos]],0):(t.typewrite(t.strings[0],0),t.arrayPos=0)},this.fadeOutDelay)},s.replaceText=function(t){this.attr?this.el.setAttribute(this.attr,t):this.isInput?this.el.value=t:"html"===this.contentType?this.el.innerHTML=t:this.el.textContent=t},s.bindFocusEvents=function(){var t=this;this.isInput&&(this.el.addEventListener("focus",function(s){t.stop()}),this.el.addEventListener("blur",function(s){t.el.value&&0!==t.el.value.length||t.start()}))},s.insertCursor=function(){this.showCursor&&(this.cursor||(this.cursor=document.createElement("span"),this.cursor.className="typed-cursor",this.cursor.setAttribute("aria-hidden",!0),this.cursor.innerHTML=this.cursorChar,this.el.parentNode&&this.el.parentNode.insertBefore(this.cursor,this.el.nextSibling)))},t}()}); +//# sourceMappingURL=typed.umd.js.map + /*! jQuery UI - v1.12.1 - 2021-07-14 * http://jqueryui.com * Includes: widget.js, position.js, jquery-1-7.js, keycode.js, unique-id.js, widgets/autocomplete.js, widgets/menu.js @@ -207,19 +215,6 @@ function checkAll(bx) { } } -/* - * jQuery dotdotdot 1.8.1 - * - * Copyright (c) Fred Heusschen - * www.frebsite.nl - * - * Plugin website: - * dotdotdot.frebsite.nl - * - * Licensed under the MIT license. - * http://en.wikipedia.org/wiki/MIT_License - */ -!function(t,e){function n(t,e,n){var r=t.children(),o=!1;t.empty();for(var i=0,d=r.length;d>i;i++){var l=r.eq(i);if(t.append(l),n&&t.append(n),a(t,e)){l.remove(),o=!0;break}n&&n.detach()}return o}function r(e,n,i,d,l){var s=!1,c="a, table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, blockquote, select, optgroup, option, textarea, script, style",u="script, .dotdotdot-keep";return e.contents().detach().each(function(){var h=this,f=t(h);if("undefined"==typeof h)return!0;if(f.is(u))e.append(f);else{if(s)return!0;e.append(f),!l||f.is(d.after)||f.find(d.after).length||e[e.is(c)?"after":"append"](l),a(i,d)&&(s=3==h.nodeType?o(f,n,i,d,l):r(f,n,i,d,l)),s||l&&l.detach()}}),n.addClass("is-truncated"),s}function o(e,n,r,o,d){var c=e[0];if(!c)return!1;var h=s(c),f=-1!==h.indexOf(" ")?" ":" ",p="letter"==o.wrap?"":f,g=h.split(p),v=-1,w=-1,b=0,y=g.length-1;for(o.fallbackToLetter&&0==b&&0==y&&(p="",g=h.split(p),y=g.length-1);y>=b&&(0!=b||0!=y);){var m=Math.floor((b+y)/2);if(m==w)break;w=m,l(c,g.slice(0,w+1).join(p)+o.ellipsis),r.children().each(function(){t(this).toggle().toggle()}),a(r,o)?(y=w,o.fallbackToLetter&&0==b&&0==y&&(p="",g=g[0].split(p),v=-1,w=-1,b=0,y=g.length-1)):(v=w,b=w)}if(-1==v||1==g.length&&0==g[0].length){var x=e.parent();e.detach();var C=d&&d.closest(x).length?d.length:0;x.contents().length>C?c=u(x.contents().eq(-1-C),n):(c=u(x,n,!0),C||x.detach()),c&&(h=i(s(c),o),l(c,h),C&&d&&t(c).parent().append(d))}else h=i(g.slice(0,v+1).join(p),o),l(c,h);return!0}function a(t,e){return t.innerHeight()>e.maxHeight}function i(e,n){for(;t.inArray(e.slice(-1),n.lastCharacter.remove)>-1;)e=e.slice(0,-1);return t.inArray(e.slice(-1),n.lastCharacter.noEllipsis)<0&&(e+=n.ellipsis),e}function d(t){return{width:t.innerWidth(),height:t.innerHeight()}}function l(t,e){t.innerText?t.innerText=e:t.nodeValue?t.nodeValue=e:t.textContent&&(t.textContent=e)}function s(t){return t.innerText?t.innerText:t.nodeValue?t.nodeValue:t.textContent?t.textContent:""}function c(t){do t=t.previousSibling;while(t&&1!==t.nodeType&&3!==t.nodeType);return t}function u(e,n,r){var o,a=e&&e[0];if(a){if(!r){if(3===a.nodeType)return a;if(t.trim(e.text()))return u(e.contents().last(),n)}for(o=c(a);!o;){if(e=e.parent(),e.is(n)||!e.length)return!1;o=c(e[0])}if(o)return u(t(o),n)}return!1}function h(e,n){return e?"string"==typeof e?(e=t(e,n),e.length?e:!1):e.jquery?e:!1:!1}function f(t){for(var e=t.innerHeight(),n=["paddingTop","paddingBottom"],r=0,o=n.length;o>r;r++){var a=parseInt(t.css(n[r]),10);isNaN(a)&&(a=0),e-=a}return e}if(!t.fn.dotdotdot){t.fn.dotdotdot=function(e){if(0==this.length)return t.fn.dotdotdot.debug('No element found for "'+this.selector+'".'),this;if(this.length>1)return this.each(function(){t(this).dotdotdot(e)});var o=this,i=o.contents();o.data("dotdotdot")&&o.trigger("destroy.dot"),o.data("dotdotdot-style",o.attr("style")||""),o.css("word-wrap","break-word"),"nowrap"===o.css("white-space")&&o.css("white-space","normal"),o.bind_events=function(){return o.bind("update.dot",function(e,d){switch(o.removeClass("is-truncated"),e.preventDefault(),e.stopPropagation(),typeof l.height){case"number":l.maxHeight=l.height;break;case"function":l.maxHeight=l.height.call(o[0]);break;default:l.maxHeight=f(o)}l.maxHeight+=l.tolerance,"undefined"!=typeof d&&(("string"==typeof d||"nodeType"in d&&1===d.nodeType)&&(d=t("<div />").append(d).contents()),d instanceof t&&(i=d)),g=o.wrapInner('<div class="dotdotdot" />').children(),g.contents().detach().end().append(i.clone(!0)).find("br").replaceWith(" <br /> ").end().css({height:"auto",width:"auto",border:"none",padding:0,margin:0});var c=!1,u=!1;return s.afterElement&&(c=s.afterElement.clone(!0),c.show(),s.afterElement.detach()),a(g,l)&&(u="children"==l.wrap?n(g,l,c):r(g,o,g,l,c)),g.replaceWith(g.contents()),g=null,t.isFunction(l.callback)&&l.callback.call(o[0],u,i),s.isTruncated=u,u}).bind("isTruncated.dot",function(t,e){return t.preventDefault(),t.stopPropagation(),"function"==typeof e&&e.call(o[0],s.isTruncated),s.isTruncated}).bind("originalContent.dot",function(t,e){return t.preventDefault(),t.stopPropagation(),"function"==typeof e&&e.call(o[0],i),i}).bind("destroy.dot",function(t){t.preventDefault(),t.stopPropagation(),o.unwatch().unbind_events().contents().detach().end().append(i).attr("style",o.data("dotdotdot-style")||"").removeClass("is-truncated").data("dotdotdot",!1)}),o},o.unbind_events=function(){return o.unbind(".dot"),o},o.watch=function(){if(o.unwatch(),"window"==l.watch){var e=t(window),n=e.width(),r=e.height();e.bind("resize.dot"+s.dotId,function(){n==e.width()&&r==e.height()&&l.windowResizeFix||(n=e.width(),r=e.height(),u&&clearInterval(u),u=setTimeout(function(){o.trigger("update.dot")},100))})}else c=d(o),u=setInterval(function(){if(o.is(":visible")){var t=d(o);c.width==t.width&&c.height==t.height||(o.trigger("update.dot"),c=t)}},500);return o},o.unwatch=function(){return t(window).unbind("resize.dot"+s.dotId),u&&clearInterval(u),o};var l=t.extend(!0,{},t.fn.dotdotdot.defaults,e),s={},c={},u=null,g=null;return l.lastCharacter.remove instanceof Array||(l.lastCharacter.remove=t.fn.dotdotdot.defaultArrays.lastCharacter.remove),l.lastCharacter.noEllipsis instanceof Array||(l.lastCharacter.noEllipsis=t.fn.dotdotdot.defaultArrays.lastCharacter.noEllipsis),s.afterElement=h(l.after,o),s.isTruncated=!1,s.dotId=p++,o.data("dotdotdot",!0).bind_events().trigger("update.dot"),l.watch&&o.watch(),o},t.fn.dotdotdot.defaults={ellipsis:"... ",wrap:"word",fallbackToLetter:!0,lastCharacter:{},tolerance:0,callback:null,after:null,height:null,watch:!1,windowResizeFix:!0},t.fn.dotdotdot.defaultArrays={lastCharacter:{remove:[" "," ",",",";",".","!","?"],noEllipsis:[]}},t.fn.dotdotdot.debug=function(t){};var p=1,g=t.fn.html;t.fn.html=function(n){return n!=e&&!t.isFunction(n)&&this.data("dotdotdot")?this.trigger("update",[n]):g.apply(this,arguments)};var v=t.fn.text;t.fn.text=function(n){return n!=e&&!t.isFunction(n)&&this.data("dotdotdot")?(n=t("<div />").text(n).html(),this.trigger("update",[n])):v.apply(this,arguments)}}}(jQuery),jQuery(document).ready(function(t){t(".dot-ellipsis").each(function(){var e=t(this).hasClass("dot-resize-update"),n=t(this).hasClass("dot-timer-update"),r=0,o=t(this).attr("class").split(/\s+/);t.each(o,function(t,e){var n=e.match(/^dot-height-(\d+)$/);null!==n&&(r=Number(n[1]))});var a=new Object;n&&(a.watch=!0),e&&(a.watch="window"),r>0&&(a.height=r),t(this).dotdotdot(a)})}),jQuery(window).load(function(){jQuery(".dot-ellipsis.dot-load-update").trigger("update.dot")}); var drawer = function () { @@ -439,15 +434,6 @@ function vote(pollid, groupurl, csrf) { }); } -/*! - * Fuel UX v3.1.0 - * Copyright 2012-2014 ExactTarget - * Licensed under the BSD-3-Clause license () - */ -!function(a){"function"==typeof define&&define.amd?define(["jquery","bootstrap"],a):a(jQuery)}(function(a){if("undefined"==typeof a)throw new Error("Fuel UX's JavaScript requires jQuery");if("undefined"==typeof a.fn.dropdown||"undefined"==typeof a.fn.collapse)throw new Error("Fuel UX's JavaScript requires Bootstrap");!function(a){var b=a.fn.checkbox,c=function(b,c){this.options=a.extend({},a.fn.checkbox.defaults,c),this.$element=a(b).is('input[type="checkbox"]')?a(b):a(b).find('input[type="checkbox"]:first'),this.$label=this.$element.parent(),this.$parent=this.$label.parent(".checkbox"),this.$toggleContainer=this.$element.attr("data-toggle"),this.state={disabled:!1,checked:!1},0===this.$parent.length&&(this.$parent=null),this.$toggleContainer=Boolean(this.$toggleContainer)?a(this.$toggleContainer):null,this.$element.on("change.fu.checkbox",a.proxy(this.itemchecked,this)),this.setState()};c.prototype={constructor:c,setState:function(a){a=a||this.$element,this.state.disabled=Boolean(a.prop("disabled")),this.state.checked=Boolean(a.is(":checked")),this._resetClasses(),this._toggleCheckedState(),this._toggleDisabledState(),this.toggleContainer()},enable:function(){this.state.disabled=!1,this.$element.attr("disabled",!1),this._resetClasses(),this.$element.trigger("enabled.fu.checkbox")},disable:function(){this.state.disabled=!0,this.$element.attr("disabled",!0),this._setDisabledClass(),this.$element.trigger("disabled.fu.checkbox")},check:function(){this.state.checked=!0,this.$element.prop("checked",!0),this._setCheckedClass(),this.$element.trigger("checked.fu.checkbox")},uncheck:function(){this.state.checked=!1,this.$element.prop("checked",!1),this._resetClasses(),this.$element.trigger("unchecked.fu.checkbox")},isChecked:function(){return this.state.checked},toggle:function(){this.state.checked=!this.state.checked,this._toggleCheckedState()},toggleContainer:function(){Boolean(this.$toggleContainer)&&(this.state.checked?(this.$toggleContainer.removeClass("hide"),this.$toggleContainer.attr("aria-hidden","false")):(this.$toggleContainer.addClass("hide"),this.$toggleContainer.attr("aria-hidden","true")))},itemchecked:function(b){this.setState(a(b.target))},destroy:function(){return this.$parent.remove(),this.$parent[0].outerHTML},_resetClasses:function(){var a=[];this.state.checked||a.push("checked"),this.state.disabled||a.push("disabled"),a=a.join(" "),this.$label.removeClass(a),this.$parent&&this.$parent.removeClass(a)},_toggleCheckedState:function(){this.state.checked?this.check():this.uncheck()},_toggleDisabledState:function(){this.state.disabled?this.disable():this.enable()},_setCheckedClass:function(){this.$label.addClass("checked"),this.$parent&&this.$parent.addClass("checked")},_setDisabledClass:function(){this.$label.addClass("disabled"),this.$parent&&this.$parent.addClass("disabled")}},a.fn.checkbox=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.checkbox"),h="object"==typeof b&&b;g||f.data("fu.checkbox",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.checkbox.defaults={},a.fn.checkbox.Constructor=c,a.fn.checkbox.noConflict=function(){return a.fn.checkbox=b,this},a(document).on("mouseover.fu.checkbox.data-api","[data-initialize=checkbox]",function(b){var c=a(b.target).closest(".checkbox").find("[type=checkbox]");c.data("fu.checkbox")||c.checkbox(c.data())}),a(function(){a("[data-initialize=checkbox] [type=checkbox]").each(function(){var b=a(this);b.data("fu.checkbox")||b.checkbox(b.data())})})}(a),function(a){var b=a.fn.combobox,c=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.combobox.defaults,c),this.$dropMenu=this.$element.find(".dropdown-menu"),this.$input=this.$element.find("input"),this.$button=this.$element.find(".btn"),this.$element.on("click.fu.combobox","a",a.proxy(this.itemclicked,this)),this.$element.on("change.fu.combobox","input",a.proxy(this.inputchanged,this)),this.$element.on("shown.bs.dropdown",a.proxy(this.menuShown,this)),this.setDefaultSelection()};c.prototype={constructor:c,destroy:function(){return this.$element.remove(),this.$element.find("input").each(function(){a(this).attr("value",a(this).val())}),this.$element[0].outerHTML},doSelect:function(a){"undefined"!=typeof a[0]?(this.$selectedItem=a,this.$input.val(this.$selectedItem.text())):this.$selectedItem=null},menuShown:function(){this.options.autoResizeMenu&&this.resizeMenu()},resizeMenu:function(){var a=this.$element.outerWidth();this.$dropMenu.outerWidth(a)},selectedItem:function(){var b=this.$selectedItem,c={};if(b){var d=this.$selectedItem.text();c=a.extend({text:d},this.$selectedItem.data())}else c={text:this.$input.val()};return c},selectByText:function(b){var c=a([]);this.$element.find("li").each(function(){return(this.textContent||this.innerText||a(this).text()||"").toLowerCase()===(b||"").toLowerCase()?(c=a(this),!1):void 0}),this.doSelect(c)},selectByValue:function(a){var b='li[data-value="'+a+'"]';this.selectBySelector(b)},selectByIndex:function(a){var b="li:eq("+a+")";this.selectBySelector(b)},selectBySelector:function(a){var b=this.$element.find(a);this.doSelect(b)},setDefaultSelection:function(){var a="li[data-selected=true]:first",b=this.$element.find(a);b.length>0&&(this.selectBySelector(a),b.removeData("selected"),b.removeAttr("data-selected"))},enable:function(){this.$element.removeClass("disabled"),this.$input.removeAttr("disabled"),this.$button.removeClass("disabled")},disable:function(){this.$element.addClass("disabled"),this.$input.attr("disabled",!0),this.$button.addClass("disabled")},itemclicked:function(b){this.$selectedItem=a(b.target).parent(),this.$input.val(this.$selectedItem.text()).trigger("change",{synthetic:!0});var c=this.selectedItem();this.$element.trigger("changed.fu.combobox",c),b.preventDefault(),this.$element.find(".dropdown-toggle").focus()},inputchanged:function(b,c){if(!c||!c.synthetic){var d=a(b.target).val();this.selectByText(d);var e=this.selectedItem();0===e.text.length&&(e={text:d}),this.$element.trigger("changed.fu.combobox",e)}}},a.fn.combobox=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.combobox"),h="object"==typeof b&&b;g||f.data("fu.combobox",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.combobox.defaults={autoResizeMenu:!0},a.fn.combobox.Constructor=c,a.fn.combobox.noConflict=function(){return a.fn.combobox=b,this},a(document).on("mousedown.fu.combobox.data-api","[data-initialize=combobox]",function(b){var c=a(b.target).closest(".combobox");c.data("fu.combobox")||c.combobox(c.data())}),a(function(){a("[data-initialize=combobox]").each(function(){var b=a(this);b.data("fu.combobox")||b.combobox(b.data())})})}(a),function(a){var b="Invalid Date",c="moment.js is not available so you cannot use this function",d=[],e=!1,f=a.fn.datepicker,g=!1,h=function(){var a,b;for(g=!0,a=0,b=d.length;b>a;a++)d[a].init.call(d[a].scope);d=[]};"function"==typeof define&&define.amd?require(["moment"],function(a){e=a,h()},function(a){var b=a.requireModules&&a.requireModules[0];"moment"===b&&h()}):h();var i=function(b,c){this.$element=a(b),this.options=a.extend(!0,{},a.fn.datepicker.defaults,c),this.$calendar=this.$element.find(".datepicker-calendar"),this.$days=this.$calendar.find(".datepicker-calendar-days"),this.$header=this.$calendar.find(".datepicker-calendar-header"),this.$headerTitle=this.$header.find(".title"),this.$input=this.$element.find("input"),this.$wheels=this.$element.find(".datepicker-wheels"),this.$wheelsMonth=this.$element.find(".datepicker-wheels-month"),this.$wheelsYear=this.$element.find(".datepicker-wheels-year"),this.artificialScrolling=!1,this.formatDate=this.options.formatDate||this.formatDate,this.inputValue=null,this.moment=!1,this.momentFormat=null,this.parseDate=this.options.parseDate||this.parseDate,this.preventBlurHide=!1,this.restricted=this.options.restricted||[],this.restrictedParsed=[],this.restrictedText=this.options.restrictedText,this.sameYearOnly=this.options.sameYearOnly,this.selectedDate=null,this.yearRestriction=null,this.$calendar.find(".datepicker-today").on("click.fu.datepicker",a.proxy(this.todayClicked,this)),this.$days.on("click.fu.datepicker","tr td button",a.proxy(this.dateClicked,this)),this.$element.find(".dropdown-menu").on("mousedown.fu.datepicker",a.proxy(this.dropdownMousedown,this)),this.$header.find(".next").on("click.fu.datepicker",a.proxy(this.next,this)),this.$header.find(".prev").on("click.fu.datepicker",a.proxy(this.prev,this)),this.$headerTitle.on("click.fu.datepicker",a.proxy(this.titleClicked,this)),this.$input.on("blur.fu.datepicker",a.proxy(this.inputBlurred,this)),this.$input.on("focus.fu.datepicker",a.proxy(this.inputFocused,this)),this.$wheels.find(".datepicker-wheels-back").on("click.fu.datepicker",a.proxy(this.backClicked,this)),this.$wheels.find(".datepicker-wheels-select").on("click.fu.datepicker",a.proxy(this.selectClicked,this)),this.$wheelsMonth.on("click.fu.datepicker","ul button",a.proxy(this.monthClicked,this)),this.$wheelsYear.on("click.fu.datepicker","ul button",a.proxy(this.yearClicked,this)),this.$wheelsYear.find("ul").on("scroll.fu.datepicker",a.proxy(this.onYearScroll,this));var f=function(){this.checkForMomentJS()&&(e=e||window.moment,this.moment=!0,this.momentFormat=this.options.momentConfig.format,this.setCulture(this.options.momentConfig.culture)),this.setRestrictedDates(this.restricted),this.setDate(this.options.date)||(this.$input.val(""),this.inputValue=this.$input.val()),this.sameYearOnly&&(this.yearRestriction=this.selectedDate?this.selectedDate.getFullYear():(new Date).getFullYear())};g?f.call(this):d.push({init:f,scope:this})};i.prototype={constructor:i,backClicked:function(){this.changeView("calendar")},changeView:function(a,b){"wheels"===a?(this.$calendar.hide().attr("aria-hidden","true"),this.$wheels.show().removeAttr("aria-hidden",""),b&&this.renderWheel(b)):(this.$wheels.hide().attr("aria-hidden","true"),this.$calendar.show().removeAttr("aria-hidden",""),b&&this.renderMonth(b))},checkForMomentJS:function(){return(a.isFunction(window.moment)||"undefined"!=typeof e&&a.isFunction(e))&&a.isPlainObject(this.options.momentConfig)&&this.options.momentConfig.culture&&this.options.momentConfig.format?!0:!1},dateClicked:function(b){var c,d=a(b.currentTarget).parents("td:first");d.hasClass("restricted")||(this.$days.find("td.selected").removeClass("selected"),d.addClass("selected"),c=new Date(d.attr("data-year"),d.attr("data-month"),d.attr("data-date")),this.selectedDate=c,this.$input.val(this.formatDate(c)),this.inputValue=this.$input.val(),this.$input.focus(),this.$element.trigger("dateClicked.fu.datepicker",c))},destroy:function(){return this.$element.remove(),this.$days.find("tbody").empty(),this.$wheelsYear.find("ul").empty(),this.$element[0].outerHTML},disable:function(){this.$element.addClass("disabled"),this.$element.find("input, button").attr("disabled","disabled"),this.$element.find(".input-group-btn").removeClass("open")},dropdownMousedown:function(){var a=this;this.preventBlurHide=!0,setTimeout(function(){a.preventBlurHide=!1},0)},enable:function(){this.$element.removeClass("disabled"),this.$element.find("input, button").removeAttr("disabled")},formatDate:function(a){var b=function(a){var b="0"+a;return b.substr(b.length-2)};return this.moment?e(a).format(this.momentFormat):b(a.getMonth()+1)+"/"+b(a.getDate())+"/"+a.getFullYear()},getCulture:function(){if(this.moment)return e.locale();throw c},getDate:function(){return this.selectedDate?this.selectedDate:new Date(0/0)},getFormat:function(){if(this.moment)return this.momentFormat;throw c},getFormattedDate:function(){return this.selectedDate?this.formatDate(this.selectedDate):b},getRestrictedDates:function(){return this.restricted},inputBlurred:function(){var a,b=this.$input.val();b!==this.inputValue&&(a=this.setDate(b),null===a?this.$element.trigger("inputParsingFailed.fu.datepicker",b):a===!1?this.$element.trigger("inputRestrictedDate.fu.datepicker",a):this.$element.trigger("changed.fu.datepicker",a)),this.preventBlurHide||this.$element.find(".input-group-btn").removeClass("open")},inputFocused:function(){this.$element.find(".input-group-btn").addClass("open")},isInvalidDate:function(a){var c=a.toString();return c===b||"NaN"===c?!0:!1},isRestricted:function(a,b,c){var d,e,f,g,h=this.restrictedParsed;if(this.sameYearOnly&&null!==this.yearRestriction&&c!==this.yearRestriction)return!0;for(d=0,f=h.length;f>d;d++)if(e=h[d].from,g=h[d].to,(c>e.year||c===e.year&&b>e.month||c===e.year&&b===e.month&&a>=e.date)&&(c<g.year||c===g.year&&b<g.month||c===g.year&&b===g.month&&a<=g.date))return!0;return!1},monthClicked:function(b){this.$wheelsMonth.find(".selected").removeClass("selected"),a(b.currentTarget).parent().addClass("selected")},next:function(){var a=this.$headerTitle.attr("data-month"),b=this.$headerTitle.attr("data-year");if(a++,a>11){if(this.sameYearOnly)return;a=0,b++}this.renderMonth(new Date(b,a,1))},onYearScroll:function(b){if(!this.artificialScrolling){var c,d,e=a(b.currentTarget),f="border-box"===e.css("box-sizing")?e.outerHeight():e.height(),g=e.get(0).scrollHeight,h=e.scrollTop(),i=f/(g-h)*100,j=h/g*100;if(5>j){for(d=parseInt(e.find("li:first").attr("data-year"),10),c=d-1;c>d-11;c--)e.prepend('<li data-year="'+c+'"><button type="button">'+c+"</button></li>");this.artificialScrolling=!0,e.scrollTop(e.get(0).scrollHeight-g+h),this.artificialScrolling=!1}else if(i>90)for(d=parseInt(e.find("li:last").attr("data-year"),10),c=d+1;d+11>c;c++)e.append('<li data-year="'+c+'"><button type="button">'+c+"</button></li>")}},parseDate:function(a){var b,c,d,f,g,h,i=this;if(a)if(this.moment){if(d=function(a,b){return b="b"===a?e(b,i.momentFormat):e(b),b.isValid()===!0?b.toDate():new Date(0/0)},h="string"==typeof a?["b","a"]:["a","b"],b=d(h[0],a),!this.isInvalidDate(b))return b;if(b=d(h[1],a),!this.isInvalidDate(b))return b}else if("string"==typeof a){if(b=new Date(Date.parse(a)),!this.isInvalidDate(b))return b;if(a=a.split("T")[0],c=/^\s*(\d{4})-(\d\d)-(\d\d)\s*$/,g=c.exec(a),g&&(f=parseInt(g[2],10),b=new Date(g[1],f-1,g[3]),f===b.getMonth()+1))return b}else if(b=new Date(a),!this.isInvalidDate(b))return b;return new Date(0/0)},prev:function(){var a=this.$headerTitle.attr("data-month"),b=this.$headerTitle.attr("data-year");if(a--,0>a){if(this.sameYearOnly)return;a=11,b--}this.renderMonth(new Date(b,a,1))},renderMonth:function(b){b=b||new Date;var c,d,e,f,g,h,i,j,k,l=new Date(b.getFullYear(),b.getMonth(),1).getDay(),m=new Date(b.getFullYear(),b.getMonth()+1,0).getDate(),n=new Date(b.getFullYear(),b.getMonth(),0).getDate(),o=this.$headerTitle.find(".month"),p=b.getMonth(),q=new Date,r=q.getDate(),s=q.getMonth(),t=q.getFullYear(),u=this.selectedDate,v=this.$days.find("tbody"),w=b.getFullYear();for(u&&(u={date:u.getDate(),month:u.getMonth(),year:u.getFullYear()}),o.find(".current").removeClass("current"),o.find('span[data-month="'+p+'"]').addClass("current"),this.$headerTitle.find(".year").text(w),this.$headerTitle.attr({"data-month":p,"data-year":w}),v.empty(),0!==l?(c=n-l+1,i=-1):(c=1,i=0),h=35-l>=m?5:6,f=0;h>f;f++){for(k=a("<tr></tr>"),g=0;7>g;g++)j=a("<td></td>"),-1===i?j.addClass("last-month"):1===i&&j.addClass("next-month"),d=p+i,e=w,0>d?(d=11,e--):d>11&&(d=0,e++),j.attr({"data-date":c,"data-month":d,"data-year":e}),e===t&&d===s&&c===r?j.addClass("current-day"):(t>e||e===t&&s>d||e===t&&d===s&&r>c)&&(j.addClass("past"),this.options.allowPastDates||j.addClass("restricted").attr("title",this.restrictedText)),this.isRestricted(c,d,e)&&j.addClass("restricted").attr("title",this.restrictedText),u&&e===u.year&&d===u.month&&c===u.date&&j.addClass("selected"),j.html(j.hasClass("restricted")?'<span><b class="datepicker-date">'+c+"</b></span>":'<span><button type="button" class="datepicker-date">'+c+"</button></span>"),c++,-1===i&&c>n?(c=1,i=0):0===i&&c>m&&(c=1,i=1),k.append(j);v.append(k)}},renderWheel:function(a){var b,c,d,e=a.getMonth(),f=this.$wheelsMonth.find("ul"),g=a.getFullYear(),h=this.$wheelsYear.find("ul");for(this.sameYearOnly?(this.$wheelsMonth.addClass("full"),this.$wheelsYear.addClass("hide")):(this.$wheelsMonth.removeClass("full"),this.$wheelsYear.removeClass("hide")),f.find(".selected").removeClass("selected"),c=f.find('li[data-month="'+e+'"]'),c.addClass("selected"),f.scrollTop(f.scrollTop()+(c.position().top-f.outerHeight()/2-c.outerHeight(!0)/2)),h.empty(),b=g-10;g+11>b;b++)h.append('<li data-year="'+b+'"><button type="button">'+b+"</button></li>");d=h.find('li[data-year="'+g+'"]'),d.addClass("selected"),this.artificialScrolling=!0,h.scrollTop(h.scrollTop()+(d.position().top-h.outerHeight()/2-d.outerHeight(!0)/2)),this.artificialScrolling=!1,c.find("button").focus()},selectClicked:function(){var a=this.$wheelsMonth.find(".selected").attr("data-month"),b=this.$wheelsYear.find(".selected").attr("data-year");this.changeView("calendar",new Date(b,a,1))},setCulture:function(a){if(!a)return!1;if(!this.moment)throw c;e.locale(a)},setDate:function(a){var b=this.parseDate(a);return this.isInvalidDate(b)?(this.selectedDate=null,this.renderMonth()):this.isRestricted(b.getDate(),b.getMonth(),b.getFullYear())?(this.selectedDate=!1,this.renderMonth()):(this.selectedDate=b,this.renderMonth(b),this.$input.val(this.formatDate(b))),this.inputValue=this.$input.val(),this.selectedDate},setFormat:function(a){if(!a)return!1;if(!this.moment)throw c;this.momentFormat=a},setRestrictedDates:function(a){var b,c,d=[],e=this,f=function(a){return a===-1/0?{date:-1/0,month:-1/0,year:-1/0}:1/0===a?{date:1/0,month:1/0,year:1/0}:(a=e.parseDate(a),{date:a.getDate(),month:a.getMonth(),year:a.getFullYear()})};for(this.restricted=a,b=0,c=a.length;c>b;b++)d.push({from:f(a[b].from),to:f(a[b].to)});this.restrictedParsed=d},titleClicked:function(){this.changeView("wheels",new Date(this.$headerTitle.attr("data-year"),this.$headerTitle.attr("data-month"),1))},todayClicked:function(){var a=new Date;(a.getMonth()+""!==this.$headerTitle.attr("data-month")||a.getFullYear()+""!==this.$headerTitle.attr("data-year"))&&this.renderMonth(a)},yearClicked:function(b){this.$wheelsYear.find(".selected").removeClass("selected"),a(b.currentTarget).parent().addClass("selected")}},a.fn.datepicker=function(b){var c,d=Array.prototype.slice.call(arguments,1),e=this.each(function(){var e=a(this),f=e.data("fu.datepicker"),g="object"==typeof b&&b;f||e.data("fu.datepicker",f=new i(this,g)),"string"==typeof b&&(c=f[b].apply(f,d))});return void 0===c?e:c},a.fn.datepicker.defaults={allowPastDates:!1,date:new Date,formatDate:null,momentConfig:{culture:"en",format:"L"},parseDate:null,restricted:[],restrictedText:"Restricted",sameYearOnly:!1},a.fn.datepicker.Constructor=i,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=f,this},a(document).on("mousedown.fu.datepicker.data-api","[data-initialize=datepicker]",function(b){var c=a(b.target).closest(".datepicker");c.data("datepicker")||c.datepicker(c.data())}),a(document).on("click.fu.datepicker.data-api",".datepicker .dropdown-menu",function(b){var c=a(b.target);(!c.is(".datepicker-date")||c.closest(".restricted").length)&&b.stopPropagation()}),a(document).on("click.fu.datepicker.data-api",".datepicker input",function(a){a.stopPropagation()}),a(function(){a("[data-initialize=datepicker]").each(function(){var b=a(this);b.data("datepicker")||b.datepicker(b.data())})})}(a),function(a){function b(b){a(b).css({visibility:"hidden"}),c(b)?b.parent().addClass("dropup"):b.parent().removeClass("dropup"),a(b).css({visibility:"visible"})}function c(a){var b=d(a),c={};return c.parentHeight=a.parent().outerHeight(),c.parentOffsetTop=a.parent().offset().top,c.dropdownHeight=a.outerHeight(),c.containerHeight=b.overflowElement.outerHeight(),c.containerOffsetTop=b.isWindow?b.overflowElement.scrollTop():b.overflowElement.offset().top,c.fromTop=c.parentOffsetTop-c.containerOffsetTop,c.fromBottom=c.containerHeight-c.parentHeight-(c.parentOffsetTop-c.containerOffsetTop),c.dropdownHeight<c.fromBottom?!1:c.dropdownHeight<c.fromTop?!0:c.dropdownHeight>=c.fromTop&&c.dropdownHeight>=c.fromBottom?c.fromTop>=c.fromBottom?!0:!1:void 0}function d(b){var c=window,d=!0;return a.each(b.parents(),function(b,e){return"visible"!==a(e).css("overflow")?(c=e,d=!1,!1):void 0}),{overflowElement:a(c),isWindow:d}}a(document.body).on("click.fu.dropdown-autoflip","[data-toggle=dropdown][data-flip]",function(){"auto"===a(this).data().flip&&b(a(this).next(".dropdown-menu"))}),a(document.body).on("suggested.fu.pillbox",function(c,d){b(a(d)),a(d).parent().addClass("open")}),a.fn.dropdownautoflip=function(){}}(a),function(a){var b=a.fn.loader,c=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.loader.defaults,c),this.begin=this.$element.is("[data-begin]")?parseInt(this.$element.attr("data-begin"),10):1,this.delay=this.$element.is("[data-delay]")?parseFloat(this.$element.attr("data-delay")):150,this.end=this.$element.is("[data-end]")?parseInt(this.$element.attr("data-end"),10):8,this.frame=this.$element.is("[data-frame]")?parseInt(this.$element.attr("data-frame"),10):this.begin,this.isIElt9=!1,this.timeout={};var d=this.msieVersion();d!==!1&&9>d&&(this.$element.addClass("iefix"),this.isIElt9=!0),this.$element.attr("data-frame",this.frame+""),this.play()};c.prototype={constructor:c,destroy:function(){return this.$element.remove(),this.$element[0].outerHTML},ieRepaint:function(){this.isIElt9&&this.$element.addClass("iefix_repaint").removeClass("iefix_repaint")},msieVersion:function(){var a=window.navigator.userAgent,b=a.indexOf("MSIE ");return b>0?parseInt(a.substring(b+5,a.indexOf(".",b)),10):!1},next:function(){this.frame++,this.frame>this.end&&(this.frame=this.begin),this.$element.attr("data-frame",this.frame+""),this.ieRepaint()},pause:function(){clearTimeout(this.timeout)},play:function(){var a=this;clearTimeout(this.timeout),this.timeout=setTimeout(function(){a.next(),a.play()},this.delay)},previous:function(){this.frame--,this.frame<this.begin&&(this.frame=this.end),this.$element.attr("data-frame",this.frame+""),this.ieRepaint()},reset:function(){this.frame=this.begin,this.$element.attr("data-frame",this.frame+""),this.ieRepaint()}},a.fn.loader=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.loader"),h="object"==typeof b&&b;g||f.data("fu.loader",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.loader.defaults={},a.fn.loader.Constructor=c,a.fn.loader.noConflict=function(){return a.fn.loader=b,this},a(function(){a("[data-initialize=loader]").each(function(){var b=a(this);b.data("fu.loader")||b.loader(b.data())})})}(a),function(a){var b=a.fn.placard,c=function(b,c){var d=this;this.$element=a(b),this.options=a.extend({},a.fn.placard.defaults,c),this.$accept=this.$element.find(".placard-accept"),this.$cancel=this.$element.find(".placard-cancel"),this.$field=this.$element.find(".placard-field"),this.$footer=this.$element.find(".placard-footer"),this.$header=this.$element.find(".placard-header"),this.$popup=this.$element.find(".placard-popup"),this.actualValue=null,this.clickStamp="_",this.previousValue="",-1===this.options.revertOnCancel&&(this.options.revertOnCancel=this.$accept.length>0?!0:!1),this.$field.on("focus.fu.placard",a.proxy(this.show,this)),this.$accept.on("click.fu.placard",a.proxy(this.complete,this,"accept")),this.$cancel.on("click.fu.placard",function(a){a.preventDefault(),d.complete("cancel")}),this.ellipsis()};c.prototype={constructor:c,complete:function(a){var b=this.options["on"+a[0].toUpperCase()+a.substring(1)],c={previousValue:this.previousValue,value:this.$field.val()};b?(b(c),this.$element.trigger(a,c)):("cancel"===a&&this.options.revertOnCancel&&this.$field.val(this.previousValue),this.$element.trigger(a,c),this.hide())},destroy:function(){return this.$element.remove(),a(document).off("click.fu.placard.externalClick."+this.clickStamp),this.$element.find("input").each(function(){a(this).attr("value",a(this).val())}),this.$element[0].outerHTML},disable:function(){this.$element.addClass("disabled"),this.$field.attr("disabled","disabled"),this.hide()},ellipsis:function(){var a,b,c;if("true"===this.$element.attr("data-ellipsis"))if(a=this.$field.get(0),this.$field.is("input"))a.scrollLeft=0;else if(a.scrollTop=0,a.clientHeight<a.scrollHeight){for(this.actualValue=this.$field.val(),this.$field.val(""),c="",b=0;a.clientHeight>=a.scrollHeight;)c+=this.actualValue[b],this.$field.val(c+"..."),b++;c=c.length>0?c.substring(0,c.length-1):"",this.$field.val(c+"...")}},enable:function(){this.$element.removeClass("disabled"),this.$field.removeAttr("disabled")},externalClickListener:function(a,b){(b===!0||this.isExternalClick(a))&&this.complete(this.options.externalClickAction)},getValue:function(){return null!==this.actualValue?this.actualValue:this.$field.val()},hide:function(){this.$element.hasClass("showing")&&(this.$element.removeClass("showing"),this.ellipsis(),a(document).off("click.fu.placard.externalClick."+this.clickStamp),this.$element.trigger("hidden.fu.placard"))},isExternalClick:function(b){var c,d,e=this.$element.get(0),f=this.options.externalClickExceptions||[],g=a(b.target);if(b.target===e||g.parents(".placard:first").get(0)===e)return!1;for(c=0,d=f.length;d>c;c++)if(g.is(f[c])||g.parents(f[c]).length>0)return!1;return!0},setValue:function(a){this.$field.val(a),this.$element.hasClass("showing")||this.ellipsis()},show:function(){var b;if(!this.$element.hasClass("showing")){if(b=a(document).find(".placard.showing"),b.length>0){if(b.data("fu.placard")&&b.data("fu.placard").options.explicit)return;b.placard("externalClickListener",{},!0)}this.previousValue=this.$field.val(),this.$element.addClass("showing"),null!==this.actualValue&&(this.$field.val(this.actualValue),this.actualValue=null),this.$header.length>0&&this.$popup.css("top","-"+this.$header.outerHeight(!0)+"px"),this.$footer.length>0&&this.$popup.css("bottom","-"+this.$footer.outerHeight(!0)+"px"),this.$element.trigger("shown.fu.placard"),this.clickStamp=(new Date).getTime()+(Math.floor(100*Math.random())+1),this.options.explicit||a(document).on("click.fu.placard.externalClick."+this.clickStamp,a.proxy(this.externalClickListener,this))}}},a.fn.placard=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.placard"),h="object"==typeof b&&b;g||f.data("fu.placard",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.placard.defaults={onAccept:void 0,onCancel:void 0,externalClickAction:"cancel",externalClickExceptions:[],explicit:!1,revertOnCancel:-1},a.fn.placard.Constructor=c,a.fn.placard.noConflict=function(){return a.fn.placard=b,this},a(document).on("focus.fu.placard.data-api","[data-initialize=placard]",function(b){var c=a(b.target).closest(".placard");c.data("fu.placard")||c.placard(c.data())}),a(function(){a("[data-initialize=placard]").each(function(){var b=a(this);b.data("fu.placard")||b.placard(b.data())})})}(a),function(a){var b=a.fn.radio,c=function(b,c){this.options=a.extend({},a.fn.radio.defaults,c),this.$radio=a(b).is('input[type="radio"]')?a(b):a(b).find('input[type="radio"]:first'),this.$label=this.$radio.parent(),this.groupName=this.$radio.attr("name"),this.$parent=this.$label.parent(".radio"),this.$toggleContainer=null,0===this.$parent.length&&(this.$parent=null);var d=this.$radio.attr("data-toggle");d&&(this.$toggleContainer=a(d)),this.setState(this.$radio),this.$radio.on("change.fu.radio",a.proxy(this.itemchecked,this))};c.prototype={constructor:c,destroy:function(){return this.$parent.remove(),this.$parent[0].outerHTML},setState:function(a){a=a||this.$radio;var b=a.is(":checked"),c=!!a.prop("disabled");this.$label.removeClass("checked"),this.$parent&&this.$parent.removeClass("checked disabled"),b===!0&&(this.$label.addClass("checked"),this.$parent&&this.$parent.addClass("checked")),c===!0&&(this.$label.addClass("disabled"),this.$parent&&this.$parent.addClass("disabled")),this.toggleContainer()},resetGroup:function(){var b=a('input[name="'+this.groupName+'"]');b.each(function(){var b=a(this).parent("label");b.removeClass("checked"),b.parent(".radio").removeClass("checked")})},enable:function(){this.$radio.attr("disabled",!1),this.$label.removeClass("disabled"),this.$parent&&this.$parent.removeClass("disabled")},disable:function(){this.$radio.attr("disabled",!0),this.$label.addClass("disabled"),this.$parent&&this.$parent.addClass("disabled")},itemchecked:function(b){var c=a(b.target);this.resetGroup(),this.setState(c)},check:function(){this.resetGroup(),this.$radio.prop("checked",!0),this.setState(this.$radio)},toggleContainer:function(){var b;this.$toggleContainer&&(this.isChecked()?(b=a('input[name="'+this.groupName+'"]'),b.each(function(){var b=a(this).attr("data-toggle");a(b).addClass("hide"),a(b).attr("aria-hidden","true")}),this.$toggleContainer.removeClass("hide"),this.$toggleContainer.attr("aria-hidden","false")):(this.$toggleContainer.addClass("hide"),this.$toggleContainer.attr("aria-hidden","true")))},uncheck:function(){this.$radio.prop("checked",!1),this.setState(this.$radio)},isChecked:function(){return this.$radio.is(":checked")}},a.fn.radio=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.radio"),h="object"==typeof b&&b;g||f.data("fu.radio",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.radio.defaults={},a.fn.radio.Constructor=c,a.fn.radio.noConflict=function(){return a.fn.radio=b,this},a(document).on("mouseover.fu.checkbox.data-api","[data-initialize=radio]",function(b){var c=a(b.target).closest(".radio").find("[type=radio]");c.data("fu.radio")||c.radio(c.data())}),a(function(){a("[data-initialize=radio] [type=radio]").each(function(){var b=a(this);b.data("fu.radio")||b.radio(b.data())})})}(a),function(a){var b=a.fn.search,c=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.search.defaults,c),this.$button=this.$element.find("button"),this.$input=this.$element.find("input"),this.$icon=this.$element.find(".glyphicon"),this.$button.on("click.fu.search",a.proxy(this.buttonclicked,this)),this.$input.on("keydown.fu.search",a.proxy(this.keypress,this)),this.$input.on("keyup.fu.search",a.proxy(this.keypressed,this)),this.activeSearch=""};c.prototype={constructor:c,destroy:function(){return this.$element.remove(),this.$element.find("input").each(function(){a(this).attr("value",a(this).val())}),this.$element[0].outerHTML},search:function(a){this.$icon.hasClass("glyphicon")&&this.$icon.removeClass("glyphicon-search").addClass("glyphicon-remove"),this.activeSearch=a,this.$element.addClass("searched"),this.$element.trigger("searched.fu.search",a)},clear:function(){this.$icon.hasClass("glyphicon")&&this.$icon.removeClass("glyphicon-remove").addClass("glyphicon-search"),this.activeSearch="",this.$input.val(""),this.$element.removeClass("searched"),this.$element.trigger("cleared.fu.search")},action:function(){var a=this.$input.val(),b=""===a||a===this.activeSearch;this.activeSearch&&b?this.clear():a&&this.search(a)},buttonclicked:function(b){b.preventDefault(),a(b.currentTarget).is(".disabled, :disabled")||this.action()},keypress:function(a){13===a.which&&a.preventDefault()},keypressed:function(a){var b,c="glyphicon-remove",d="glyphicon-search";13===a.which?(a.preventDefault(),this.action()):(b=this.$input.val(),b?b!==this.activeSearch?this.$icon.removeClass(c).addClass(d):this.$icon.removeClass(d).addClass(c):this.clear())},disable:function(){this.$element.addClass("disabled"),this.$input.attr("disabled","disabled"),this.$button.addClass("disabled")},enable:function(){this.$element.removeClass("disabled"),this.$input.removeAttr("disabled"),this.$button.removeClass("disabled")}},a.fn.search=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.search"),h="object"==typeof b&&b;g||f.data("fu.search",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e)) -});return void 0===d?f:d},a.fn.search.defaults={},a.fn.search.Constructor=c,a.fn.search.noConflict=function(){return a.fn.search=b,this},a(document).on("mousedown.fu.search.data-api","[data-initialize=search]",function(b){var c=a(b.target).closest(".search");c.data("fu.search")||c.search(c.data())}),a(function(){a("[data-initialize=search]").each(function(){var b=a(this);b.data("fu.search")||b.search(b.data())})})}(a),function(a){var b=a.fn.selectlist,c=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.selectlist.defaults,c),this.$button=this.$element.find(".btn.dropdown-toggle"),this.$hiddenField=this.$element.find(".hidden-field"),this.$label=this.$element.find(".selected-label"),this.$element.on("click.fu.selectlist",".dropdown-menu a",a.proxy(this.itemClicked,this)),this.setDefaultSelection(),"auto"===c.resize&&this.resize()};c.prototype={constructor:c,destroy:function(){return this.$element.remove(),this.$element[0].outerHTML},doSelect:function(b){var c;this.$selectedItem=c=b,this.$hiddenField.val(this.$selectedItem.attr("data-value")),this.$label.html(a(this.$selectedItem.children()[0]).html()),this.$element.find("li").each(function(){c.is(a(this))?a(this).attr("data-selected",!0):a(this).removeData("selected").removeAttr("data-selected")})},itemClicked:function(b){this.$element.trigger("clicked.fu.selectlist",this.$selectedItem),b.preventDefault(),a(b.target).parent().is(this.$selectedItem)||this.itemChanged(b),this.$element.find(".dropdown-toggle").focus()},itemChanged:function(b){this.doSelect(a(b.target).closest("li"));var c=this.selectedItem();this.$element.trigger("changed.fu.selectlist",c)},resize:function(){var b=0,c=a("<div/>").addClass("selectlist-sizer"),d=0;Boolean(a(document).find("html").hasClass("fuelux"))?a(document.body).append(c):a(".fuelux:first").append(c),this.$element.find("a").each(function(){c.text(a(this).text()),b=c.outerWidth(),b>d&&(d=b)}),c.remove(),this.$label.width(d)},selectedItem:function(){var b=this.$selectedItem.text();return a.extend({text:b},this.$selectedItem.data())},selectByText:function(b){var c=a([]);this.$element.find("li").each(function(){return(this.textContent||this.innerText||a(this).text()||"").toLowerCase()===(b||"").toLowerCase()?(c=a(this),!1):void 0}),this.doSelect(c)},selectByValue:function(a){var b='li[data-value="'+a+'"]';this.selectBySelector(b)},selectByIndex:function(a){var b="li:eq("+a+")";this.selectBySelector(b)},selectBySelector:function(a){var b=this.$element.find(a);this.doSelect(b)},setDefaultSelection:function(){var a=this.$element.find("li[data-selected=true]").eq(0);0===a.length&&(a=this.$element.find("li").has("a").eq(0)),this.doSelect(a)},enable:function(){this.$element.removeClass("disabled"),this.$button.removeClass("disabled")},disable:function(){this.$element.addClass("disabled"),this.$button.addClass("disabled")}},a.fn.selectlist=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.selectlist"),h="object"==typeof b&&b;g||f.data("fu.selectlist",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.selectlist.defaults={},a.fn.selectlist.Constructor=c,a.fn.selectlist.noConflict=function(){return a.fn.selectlist=b,this},a(document).on("mousedown.fu.selectlist.data-api","[data-initialize=selectlist]",function(b){var c=a(b.target).closest(".selectlist");c.data("fu.selectlist")||c.selectlist(c.data())}),a(function(){a("[data-initialize=selectlist]").each(function(){var b=a(this);b.data("fu.selectlist")||b.selectlist(b.data())})})}(a),function(a){var b=a.fn.spinbox,c=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.spinbox.defaults,c),this.$input=this.$element.find(".spinbox-input"),this.$element.on("focusin.fu.spinbox",this.$input,a.proxy(this.changeFlag,this)),this.$element.on("focusout.fu.spinbox",this.$input,a.proxy(this.change,this)),this.$element.on("keydown.fu.spinbox",this.$input,a.proxy(this.keydown,this)),this.$element.on("keyup.fu.spinbox",this.$input,a.proxy(this.keyup,this)),this.bindMousewheelListeners(),this.mousewheelTimeout={},this.options.hold?(this.$element.on("mousedown.fu.spinbox",".spinbox-up",a.proxy(function(){this.startSpin(!0)},this)),this.$element.on("mouseup.fu.spinbox",".spinbox-up, .spinbox-down",a.proxy(this.stopSpin,this)),this.$element.on("mouseout.fu.spinbox",".spinbox-up, .spinbox-down",a.proxy(this.stopSpin,this)),this.$element.on("mousedown.fu.spinbox",".spinbox-down",a.proxy(function(){this.startSpin(!1)},this))):(this.$element.on("click.fu.spinbox",".spinbox-up",a.proxy(function(){this.step(!0)},this)),this.$element.on("click.fu.spinbox",".spinbox-down",a.proxy(function(){this.step(!1)},this))),this.switches={count:1,enabled:!0},this.switches.speed="medium"===this.options.speed?300:"fast"===this.options.speed?100:500,this.lastValue=this.options.value,this.render(),this.options.disabled&&this.disable()};c.prototype={constructor:c,destroy:function(){return this.$element.remove(),this.$element.find("input").each(function(){a(this).attr("value",a(this).val())}),this.$element[0].outerHTML},render:function(){var b=this.parseInput(this.$input.val()),c="";""!==b&&0===this.options.value?this.value(b):this.output(this.options.value),this.options.units.length&&a.each(this.options.units,function(a,b){b.length>c.length&&(c=b)})},output:function(a,b){return a=(a+"").split(".").join(this.options.decimalMark),b=b||!0,b&&this.$input.val(a),a},parseInput:function(a){return a=(a+"").split(this.options.decimalMark).join(".")},change:function(){var a=this.parseInput(this.$input.val())||"";this.options.units.length||"."!==this.options.decimalMark?a=this.parseValueWithUnit(a):a/1?a=this.options.value=this.checkMaxMin(a/1):(a=this.checkMaxMin(a.replace(/[^0-9.-]/g,"")||""),this.options.value=a/1),this.output(a),this.changeFlag=!1,this.triggerChangedEvent()},changeFlag:function(){this.changeFlag=!0},stopSpin:function(){void 0!==this.switches.timeout&&(clearTimeout(this.switches.timeout),this.switches.count=1,this.triggerChangedEvent())},triggerChangedEvent:function(){var a=this.value();a!==this.lastValue&&(this.lastValue=a,this.$element.trigger("changed.fu.spinbox",this.output(a,!1)))},startSpin:function(b){if(!this.options.disabled){var c=this.switches.count;1===c?(this.step(b),c=1):c=3>c?1.5:8>c?2.5:4,this.switches.timeout=setTimeout(a.proxy(function(){this.iterate(b)},this),this.switches.speed/c),this.switches.count++}},iterate:function(a){this.step(a),this.startSpin(a)},step:function(a){var b,c,d,e;if(this.changeFlag&&this.change(),d=this.options.value,e=a?this.options.max:this.options.min,a?e>d:d>e){var f=d+(a?1:-1)*this.options.step;this.options.step%1!==0&&(b=(this.options.step+"").split(".")[1].length,c=Math.pow(10,b),f=Math.round(f*c)/c),this.value((a?f>e:e>f)?e:f)}else if(this.options.cycle){var g=a?this.options.min:this.options.max;this.value(g)}},value:function(a){return a||0===a?this.options.units.length||"."!==this.options.decimalMark?(this.output(this.parseValueWithUnit(a+(this.unit||""))),this):!isNaN(parseFloat(a))&&isFinite(a)?(this.options.value=a/1,this.output(a+(this.unit?this.unit:"")),this):void 0:(this.changeFlag&&this.change(),this.unit?this.options.value+this.unit:this.output(this.options.value,!1))},isUnitLegal:function(b){var c;return a.each(this.options.units,function(a,d){return d.toLowerCase()===b.toLowerCase()?(c=b.toLowerCase(),!1):void 0}),c},parseValueWithUnit:function(a){var b=a.replace(/[^a-zA-Z]/g,""),c=a.replace(/[^0-9.-]/g,"");return b&&(b=this.isUnitLegal(b)),this.options.value=this.checkMaxMin(c/1),this.unit=b||void 0,this.options.value+(b||"")},checkMaxMin:function(a){return isNaN(parseFloat(a))?a:(a<=this.options.max&&a>=this.options.min||(a=a>=this.options.max?this.options.max:this.options.min),a)},disable:function(){this.options.disabled=!0,this.$element.addClass("disabled"),this.$input.attr("disabled",""),this.$element.find("button").addClass("disabled")},enable:function(){this.options.disabled=!1,this.$element.removeClass("disabled"),this.$input.removeAttr("disabled"),this.$element.find("button").removeClass("disabled")},keydown:function(a){var b=a.keyCode;38===b?this.step(!0):40===b&&this.step(!1)},keyup:function(a){var b=a.keyCode;(38===b||40===b)&&this.triggerChangedEvent()},bindMousewheelListeners:function(){var b=this.$input.get(0);b.addEventListener?(b.addEventListener("mousewheel",a.proxy(this.mousewheelHandler,this),!1),b.addEventListener("DOMMouseScroll",a.proxy(this.mousewheelHandler,this),!1)):b.attachEvent("onmousewheel",a.proxy(this.mousewheelHandler,this))},mousewheelHandler:function(a){var b=window.event||a,c=Math.max(-1,Math.min(1,b.wheelDelta||-b.detail)),d=this;return clearTimeout(this.mousewheelTimeout),this.mousewheelTimeout=setTimeout(function(){d.triggerChangedEvent()},300),this.step(0>c?!0:!1),b.preventDefault?b.preventDefault():b.returnValue=!1,!1}},a.fn.spinbox=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.spinbox"),h="object"==typeof b&&b;g||f.data("fu.spinbox",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.spinbox.defaults={value:0,min:0,max:999,step:1,hold:!0,speed:"medium",disabled:!1,cycle:!1,units:[],decimalMark:"."},a.fn.spinbox.Constructor=c,a.fn.spinbox.noConflict=function(){return a.fn.spinbox=b,this},a(document).on("mousedown.fu.spinbox.data-api","[data-initialize=spinbox]",function(b){var c=a(b.target).closest(".spinbox");c.data("fu.spinbox")||c.spinbox(c.data())}),a(function(){a("[data-initialize=spinbox]").each(function(){var b=a(this);b.data("fu.spinbox")||b.spinbox(b.data())})})}(a),function(a){var b=a.fn.tree,c=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.tree.defaults,c),this.$element.on("click.fu.tree",".tree-item",a.proxy(function(a){this.selectItem(a.currentTarget)},this)),this.$element.on("click.fu.tree",".tree-branch-name",a.proxy(function(a){this.openFolder(a.currentTarget)},this)),this.options.folderSelect&&(this.$element.off("click.fu.tree",".tree-branch-name"),this.$element.on("click.fu.tree",".icon-caret",a.proxy(function(b){this.openFolder(a(b.currentTarget).parent())},this)),this.$element.on("click.fu.tree",".tree-branch-name",a.proxy(function(b){this.selectFolder(a(b.currentTarget))},this))),this.render()};c.prototype={constructor:c,destroy:function(){return this.$element.find("li:not([data-template])").remove(),this.$element.remove(),this.$element[0].outerHTML},render:function(){this.populate(this.$element)},populate:function(b){var c=this,d=b.hasClass("tree")?b:b.parent(),e=d.find(".tree-loader:eq(0)");e.removeClass("hide"),this.options.dataSource(d.data(),function(f){e.addClass("hide"),a.each(f.data,function(e,f){var g;"folder"===f.type?(g=c.$element.find("[data-template=treebranch]:eq(0)").clone().removeClass("hide").removeAttr("data-template"),g.data(f),g.find(".tree-branch-name > .tree-label").html(f.name)):"item"===f.type&&(g=c.$element.find("[data-template=treeitem]:eq(0)").clone().removeClass("hide").removeAttr("data-template"),g.find(".tree-item-name > .tree-label").html(f.name),g.data(f));var h=f.attr||f.dataAttributes||[];a.each(h,function(a,b){switch(a){case"cssClass":case"class":case"className":g.addClass(b);break;case"data-icon":g.find(".icon-item").removeClass().addClass("icon-item "+b),g.attr(a,b);break;case"id":g.attr(a,b),g.attr("aria-labelledby",b+"-label"),g.find(".tree-branch-name > .tree-label").attr("id",b+"-label");break;default:g.attr(a,b)}}),b.hasClass("tree-branch-header")?d.find(".tree-branch-children:eq(0)").append(g):b.append(g)}),c.$element.trigger("loaded.fu.tree",d)})},selectItem:function(b){var c=a(b),d=c.data(),e=this.$element.find(".tree-selected"),f=[],g=c.find(".icon-item");this.options.multiSelect?a.each(e,function(b,d){var e=a(d);e[0]!==c[0]&&f.push(a(d).data())}):e[0]!==c[0]&&(e.removeClass("tree-selected").find(".glyphicon").removeClass("glyphicon-ok").addClass("fueluxicon-bullet"),f.push(d));var h="selected";c.hasClass("tree-selected")?(h="deselected",c.removeClass("tree-selected"),(g.hasClass("glyphicon-ok")||g.hasClass("fueluxicon-bullet"))&&g.removeClass("glyphicon-ok").addClass("fueluxicon-bullet")):(c.addClass("tree-selected"),(g.hasClass("glyphicon-ok")||g.hasClass("fueluxicon-bullet"))&&g.removeClass("fueluxicon-bullet").addClass("glyphicon-ok"),this.options.multiSelect&&f.push(d)),this.$element.trigger(h+".fu.tree",{target:d,selected:f}),c.trigger("updated.fu.tree",{selected:f,item:c,eventType:h})},openFolder:function(b){var c,d,e,f=a(b);this.options.folderSelect||(f=a(b).parent()),c=f.closest(".tree-branch"),d=c.find(".tree-branch-children"),e=d.eq(0);var g,h,i;f.find(".glyphicon-folder-close").length?(g="opened",h=".glyphicon-folder-close",i="glyphicon-folder-open",c.addClass("tree-open"),c.attr("aria-expanded","true"),e.removeClass("hide"),d.children().length||this.populate(d)):f.find(".glyphicon-folder-open")&&(g="closed",h=".glyphicon-folder-open",i="glyphicon-folder-close",c.removeClass("tree-open"),c.attr("aria-expanded","false"),e.addClass("hide"),this.options.cacheItems||e.empty()),c.find("> .tree-branch-header .icon-folder").eq(0).removeClass("glyphicon-folder-close glyphicon-folder-open").addClass(i),this.$element.trigger(g+"fu.tree",c.data())},selectFolder:function(b){var c=a(b),d=c.closest(".tree-branch"),e=this.$element.find(".tree-branch.tree-selected"),f=d.data(),g=[],h="selected";d.hasClass("tree-selected")?(h="deselected",d.removeClass("tree-selected")):d.addClass("tree-selected"),this.options.multiSelect?(e=this.$element.find(".tree-branch.tree-selected"),a.each(e,function(b,d){var e=a(d);e[0]!==c[0]&&g.push(a(d).data())})):e[0]!==c[0]&&(e.removeClass("tree-selected"),g.push(f)),this.$element.trigger(h+".fu.tree",{target:f,selected:g}),c.trigger("updated.fu.tree",{selected:g,item:c,eventType:h})},selectedItems:function(){var b=this.$element.find(".tree-selected"),c=[];return a.each(b,function(b,d){c.push(a(d).data())}),c},collapse:function(){var b=this.options.cacheItems;this.$element.find(".icon-folder-open").each(function(){var c=a(this).removeClass("icon-folder-close icon-folder-open").addClass("icon-folder-close"),d=c.parent().parent(),e=d.children(".tree-branch-children");e.addClass("hide"),b||e.empty()})}},a.fn.tree=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.tree"),h="object"==typeof b&&b;g||f.data("fu.tree",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.tree.defaults={dataSource:function(){},multiSelect:!1,cacheItems:!0,folderSelect:!0},a.fn.tree.Constructor=c,a.fn.tree.noConflict=function(){return a.fn.tree=b,this}}(a),function(a){var b=a.fn.wizard,c=function(b,c){var d;this.$element=a(b),this.options=a.extend({},a.fn.wizard.defaults,c),this.options.disablePreviousStep="previous"===this.$element.attr("data-restrict")?!0:this.options.disablePreviousStep,this.currentStep=this.options.selectedItem.step,this.numSteps=this.$element.find(".steps li").length,this.$prevBtn=this.$element.find("button.btn-prev"),this.$nextBtn=this.$element.find("button.btn-next"),d=this.$nextBtn.children().detach(),this.nextText=a.trim(this.$nextBtn.text()),this.$nextBtn.append(d),this.$prevBtn.on("click.fu.wizard",a.proxy(this.previous,this)),this.$nextBtn.on("click.fu.wizard",a.proxy(this.next,this)),this.$element.on("click.fu.wizard","li.complete",a.proxy(this.stepclicked,this)),this.selectedItem(this.options.selectedItem),this.options.disablePreviousStep&&(this.$prevBtn.attr("disabled",!0),this.$element.find(".steps").addClass("previous-disabled"))};c.prototype={constructor:c,destroy:function(){return this.$element.remove(),this.$element[0].outerHTML},addSteps:function(b){var c,d,e,f,g,h,i=[].slice.call(arguments).slice(1),j=this.$element.find(".steps"),k=this.$element.find(".step-content");for(b=-1===b||b>this.numSteps+1?this.numSteps+1:b,i[0]instanceof Array&&(i=i[0]),g=j.find("li:nth-child("+b+")"),f=k.find(".step-pane:nth-child("+b+")"),g.length<1&&(g=null),c=0,d=i.length;d>c;c++)h=a('<li data-step="'+b+'"><span class="badge badge-info"></span></li>'),h.append(i[c].label||"").append('<span class="chevron"></span>'),h.find(".badge").append(i[c].badge||b),e=a('<div class="step-pane" data-step="'+b+'"></div>'),e.append(i[c].pane||""),g?(g.before(h),f.before(e)):(j.append(h),k.append(e)),b++;this.syncSteps(),this.numSteps=j.find("li").length,this.setState()},removeSteps:function(b,c){var d,e="nextAll",f=0,g=this.$element.find(".steps"),h=this.$element.find(".step-content");c=void 0!==c?c:1,b>g.find("li").length?d=g.find("li:last"):(d=g.find("li:nth-child("+b+")").prev(),d.length<1&&(e="children",d=g)),d[e]().each(function(){var b=a(this),d=b.attr("data-step");return c>f?(b.remove(),h.find('.step-pane[data-step="'+d+'"]:first').remove(),void f++):!1}),this.syncSteps(),this.numSteps=g.find("li").length,this.setState()},setState:function(){var b=this.currentStep>1,c=1===this.currentStep,d=this.currentStep===this.numSteps;this.options.disablePreviousStep||this.$prevBtn.attr("disabled",c===!0||b===!1);var e=this.$nextBtn.attr("data-last");if(e){this.lastText=e;var f=this.nextText;d===!0?(f=this.lastText,this.$element.addClass("complete")):this.$element.removeClass("complete");var g=this.$nextBtn.children().detach();this.$nextBtn.text(f).append(g)}var h=this.$element.find(".steps li");h.removeClass("active").removeClass("complete"),h.find("span.badge").removeClass("badge-info").removeClass("badge-success");var i=".steps li:lt("+(this.currentStep-1)+")",j=this.$element.find(i);j.addClass("complete"),j.find("span.badge").addClass("badge-success");var k=".steps li:eq("+(this.currentStep-1)+")",l=this.$element.find(k);l.addClass("active"),l.find("span.badge").addClass("badge-info");var m=this.$element.find(".step-content"),n=l.attr("data-step");m.find(".step-pane").removeClass("active"),m.find('.step-pane[data-step="'+n+'"]:first').addClass("active"),this.$element.find(".steps").first().attr("style","margin-left: 0");var o=0;this.$element.find(".steps > li").each(function(){o+=a(this).outerWidth()});var p=0;if(p=this.$element.find(".actions").length?this.$element.width()-this.$element.find(".actions").first().outerWidth():this.$element.width(),o>p){var q=o-p;this.$element.find(".steps").first().attr("style","margin-left: -"+q+"px"),this.$element.find("li.active").first().position().left<200&&(q+=this.$element.find("li.active").first().position().left-200,1>q?this.$element.find(".steps").first().attr("style","margin-left: 0"):this.$element.find(".steps").first().attr("style","margin-left: -"+q+"px"))}if("undefined"!=typeof this.initialized){var r=a.Event("changed.fu.wizard");this.$element.trigger(r,{step:this.currentStep})}this.initialized=!0},stepclicked:function(b){var c=a(b.currentTarget),d=this.$element.find(".steps li").index(c),e=!0;if(this.options.disablePreviousStep&&d<this.currentStep&&(e=!1),e){var f=a.Event("stepclicked.fu.wizard");if(this.$element.trigger(f,{step:d+1}),f.isDefaultPrevented())return;this.currentStep=d+1,this.setState()}},syncSteps:function(){var b=1,c=this.$element.find(".steps"),d=this.$element.find(".step-content");c.children().each(function(){var c=a(this),e=c.find(".badge"),f=c.attr("data-step");isNaN(parseInt(e.html(),10))||e.html(b),c.attr("data-step",b),d.find('.step-pane[data-step="'+f+'"]:last').attr("data-step",b),b++})},previous:function(){var b=this.currentStep>1;if(this.options.disablePreviousStep&&(b=!1),b){var c=a.Event("actionclicked.fu.wizard");if(this.$element.trigger(c,{step:this.currentStep,direction:"previous"}),c.isDefaultPrevented())return;this.currentStep-=1,this.setState()}this.$prevBtn.is(":disabled")?this.$nextBtn.focus():this.$prevBtn.focus()},next:function(){var b=this.currentStep+1<=this.numSteps,c=this.currentStep===this.numSteps;if(b){var d=a.Event("actionclicked.fu.wizard");if(this.$element.trigger(d,{step:this.currentStep,direction:"next"}),d.isDefaultPrevented())return;this.currentStep+=1,this.setState()}else c&&this.$element.trigger("finished.fu.wizard");this.$nextBtn.is(":disabled")?this.$prevBtn.focus():this.$nextBtn.focus()},selectedItem:function(a){var b,c;return a?(c=a.step||-1,c>=1&&c<=this.numSteps?(this.currentStep=c,this.setState()):(c=this.$element.find(".steps li.active:first").attr("data-step"),isNaN(c)||(this.currentStep=parseInt(c,10),this.setState())),b=this):b={step:this.currentStep},b}},a.fn.wizard=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.wizard"),h="object"==typeof b&&b;g||f.data("fu.wizard",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.wizard.defaults={disablePreviousStep:!1,selectedItem:{step:-1}},a.fn.wizard.Constructor=c,a.fn.wizard.noConflict=function(){return a.fn.wizard=b,this},a(document).on("mouseover.fu.wizard.data-api","[data-initialize=wizard]",function(b){var c=a(b.target).closest(".wizard");c.data("fu.wizard")||c.wizard(c.data())}),a(function(){a("[data-initialize=wizard]").each(function(){var b=a(this);b.data("fu.wizard")||b.wizard(b.data())})})}(a),function(a){var b=a.fn.infinitescroll,c=function(b,c){this.$element=a(b),this.$element.addClass("infinitescroll"),this.options=a.extend({},a.fn.infinitescroll.defaults,c),this.curScrollTop=this.$element.scrollTop(),this.curPercentage=this.getPercentage(),this.fetchingData=!1,this.$element.on("scroll.fu.infinitescroll",a.proxy(this.onScroll,this)),this.onScroll()};c.prototype={constructor:c,destroy:function(){return this.$element.remove(),this.$element.empty(),this.$element[0].outerHTML},disable:function(){this.$element.off("scroll.fu.infinitescroll")},enable:function(){this.$element.on("scroll.fu.infinitescroll",a.proxy(this.onScroll,this))},end:function(b){var c=a('<div class="infinitescroll-end"></div>');c.append(b?b:"---------"),this.$element.append(c),this.disable()},getPercentage:function(){var a="border-box"===this.$element.css("box-sizing")?this.$element.outerHeight():this.$element.height(),b=this.$element.get(0).scrollHeight;return b>a?a/(b-this.curScrollTop)*100:0},fetchData:function(b){var c,d=a('<div class="infinitescroll-load"></div>'),e=this,f=function(){var b={percentage:e.curPercentage,scrollTop:e.curScrollTop},c=a('<div class="loader"></div>');d.append(c),c.loader(),e.options.dataSource&&e.options.dataSource(b,function(a){var b;d.remove(),a.content&&e.$element.append(a.content),a.end&&(b=a.end!==!0?a.end:void 0,e.end(b)),e.fetchingData=!1})};this.fetchingData=!0,this.$element.append(d),this.options.hybrid&&b!==!0?(c=a('<button type="button" class="btn btn-primary"></button>'),c.append("object"==typeof this.options.hybrid?this.options.hybrid.label:'<span class="glyphicon glyphicon-repeat"></span>'),c.on("click.fu.infinitescroll",function(){c.remove(),f()}),d.append(c)):f()},onScroll:function(){this.curScrollTop=this.$element.scrollTop(),this.curPercentage=this.getPercentage(),!this.fetchingData&&this.curPercentage>=this.options.percentage&&this.fetchData()}},a.fn.infinitescroll=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.infinitescroll"),h="object"==typeof b&&b;g||f.data("fu.infinitescroll",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.infinitescroll.defaults={dataSource:null,hybrid:!1,percentage:95},a.fn.infinitescroll.Constructor=c,a.fn.infinitescroll.noConflict=function(){return a.fn.infinitescroll=b,this}}(a),function(a){var b=a.fn.pillbox,c=function(b,c){this.$element=a(b),this.$moreCount=this.$element.find(".pillbox-more-count"),this.$pillGroup=this.$element.find(".pill-group"),this.$addItem=this.$element.find(".pillbox-add-item"),this.$addItemWrap=this.$addItem.parent(),this.$suggest=this.$element.find(".suggest"),this.$pillHTML='<li class="btn btn-default pill"> <span></span> <span class="glyphicon glyphicon-close"> <span class="sr-only">Remove</span> </span></li>',this.options=a.extend({},a.fn.pillbox.defaults,c),-1===this.options.readonly?void 0!==this.$element.attr("data-readonly")&&this.readonly(!0):this.options.readonly&&this.readonly(!0),this.acceptKeyCodes=this._generateObject(this.options.acceptKeyCodes),this.$element.on("click.fu.pillbox",".pill-group > .pill",a.proxy(this.itemClicked,this)),this.$element.on("click.fu.pillbox",a.proxy(this.inputFocus,this)),this.$element.on("keydown.fu.pillbox",".pillbox-add-item",a.proxy(this.inputEvent,this)),this.options.onKeyDown&&this.$element.on("mousedown.fu.pillbox",".suggest > li",a.proxy(this.suggestionClick,this)),this.options.edit&&(this.$element.addClass("pills-editable"),this.$element.on("blur.fu.pillbox",".pillbox-add-item",a.proxy(this.cancelEdit,this)))};c.prototype={constructor:c,destroy:function(){return this.$element.remove(),this.$element[0].outerHTML},items:function(){var b=this;return this.$pillGroup.children(".pill").map(function(){return b.getItemData(a(this))}).get()},itemClicked:function(b){var c,d=a(b.target);if(b.preventDefault(),b.stopPropagation(),this._closeSuggestions(),d.hasClass("pill"))c=d;else if(c=d.parent(),void 0===this.$element.attr("data-readonly")){if(d.hasClass("glyphicon-close"))return this.options.onRemove?this.options.onRemove(this.getItemData(c,{el:c}),a.proxy(this._removeElement,this)):this._removeElement(this.getItemData(c,{el:c})),!1;if(this.options.edit){if(c.find(".pillbox-list-edit").length)return!1;this.openEdit(c)}}this.$element.trigger("clicked.fu.pillbox",this.getItemData(c))},readonly:function(a){a?this.$element.attr("data-readonly","readonly"):this.$element.removeAttr("data-readonly"),this.options.truncate&&this.truncate(a)},suggestionClick:function(b){var c=a(b.currentTarget),d={text:c.html(),value:c.data("value")};b.preventDefault(),this.$addItem.val(""),c.data("attr")&&(d.attr=JSON.parse(c.data("attr"))),d.data=c.data("data"),this.addItems(d,!0),this._closeSuggestions()},itemCount:function(){return this.$pillGroup.children(".pill").length},addItems:function(){var b,c,d,e=this;!isFinite(String(arguments[0]))||arguments[0]instanceof Array?(b=[].slice.call(arguments).slice(0),d=b[1]&&!b[1].text):(b=[].slice.call(arguments).slice(1),c=arguments[0]),b[0]instanceof Array&&(b=b[0]),b.length&&(a.each(b,function(a,c){var d={text:c.text,value:c.value?c.value:c.text,el:e.$pillHTML};c.attr&&(d.attr=c.attr),c.data&&(d.data=c.data),b[a]=d}),this.options.edit&&this.currentEdit&&(b[0].el=this.currentEdit.wrap("<div></div>").parent().html()),d&&b.pop(1),e.options.onAdd&&d?this.options.edit&&this.currentEdit?e.options.onAdd(b[0],a.proxy(e.saveEdit,this)):e.options.onAdd(b[0],a.proxy(e.placeItems,this)):this.options.edit&&this.currentEdit?e.saveEdit(b):c?e.placeItems(c,b):e.placeItems(b,d))},removeItems:function(a,b){var c,d,e=this;if(a)for(b=b?b:1,c=0;b>c&&(d=e.$pillGroup.find("> .pill:nth-child("+a+")"),d);c++)d.remove();else this.$pillGroup.find(".pill").remove(),this._removePillTrigger({method:"removeAll"})},placeItems:function(){var b,c,d,e,f=[];!isFinite(String(arguments[0]))||arguments[0]instanceof Array?(b=[].slice.call(arguments).slice(0),e=b[1]&&!b[1].text):(b=[].slice.call(arguments).slice(1),c=arguments[0]),b[0]instanceof Array&&(b=b[0]),b.length&&(a.each(b,function(b,c){var d=a(c.el);d.attr("data-value",c.value),d.find("span:first").html(c.text),c.attr&&a.each(c.attr,function(a,b){"cssClass"===a||"class"===a?d.addClass(b):d.attr(a,b)}),c.data&&d.data("data",c.data),f.push(d)}),this.$pillGroup.children(".pill").length>0?c?(d=this.$pillGroup.find(".pill:nth-child("+c+")"),d.length?d.before(f):this.$pillGroup.children(".pill:last").after(f)):this.$pillGroup.children(".pill:last").after(f):this.$pillGroup.prepend(f),e&&this.$element.trigger("added.fu.pillbox",{text:b[0].text,value:b[0].value}))},inputEvent:function(a){var b,c,d,e,f=this,g=this.$addItem.val();if(this.acceptKeyCodes[a.keyCode])return this.options.onKeyDown&&this._isSuggestionsOpen()&&(e=this.$suggest.find(".pillbox-suggest-sel"),e.length&&(g=e.html(),b=e.data("value"),c=e.data("attr"))),g.length&&(this._closeSuggestions(),this.$addItem.hide(),c?this.addItems({text:g,value:b,attr:JSON.parse(c)},!0):this.addItems({text:g,value:b},!0),setTimeout(function(){f.$addItem.show().val("").attr({size:10})},0)),a.preventDefault(),!0;if(8===a.keyCode||46===a.keyCode){if(!g.length)return a.preventDefault(),this.options.edit&&this.currentEdit?(this.cancelEdit(),!0):(this._closeSuggestions(),d=this.$pillGroup.children(".pill:last"),d.hasClass("pillbox-highlight")?this._removeElement(this.getItemData(d,{el:d})):d.addClass("pillbox-highlight"),!0)}else g.length>10&&this.$addItem.width()<this.$pillGroup.width()-6&&this.$addItem.attr({size:g.length+3});if(this.$pillGroup.find(".pill").removeClass("pillbox-highlight"),this.options.onKeyDown){if(9===a.keyCode||38===a.keyCode||40===a.keyCode)return this._isSuggestionsOpen()&&this._keySuggestions(a),!0;this.callbackId=a.timeStamp,this.options.onKeyDown({event:a,value:g},function(b){f._openSuggestions(a,b)})}},openEdit:function(a){var b=a.index()+1,c=this.$addItemWrap.detach().hide();this.$pillGroup.find(".pill:nth-child("+b+")").before(c),this.currentEdit=a.detach(),c.addClass("editing"),this.$addItem.val(a.find("span:first").html()),c.show(),this.$addItem.focus().select()},cancelEdit:function(a){var b;return this.currentEdit?(this._closeSuggestions(),a&&this.$addItemWrap.before(this.currentEdit),this.currentEdit=!1,b=this.$addItemWrap.detach(),b.removeClass("editing"),this.$addItem.val(""),void this.$pillGroup.append(b)):!1},saveEdit:function(){var b=arguments[0][0]?arguments[0][0]:arguments[0];this.currentEdit=a(b.el),this.currentEdit.data("value",b.value),this.currentEdit.find("span:first").html(b.text),this.$addItemWrap.hide(),this.$addItemWrap.before(this.currentEdit),this.currentEdit=!1,this.$addItem.val(""),this.$addItemWrap.removeClass("editing"),this.$pillGroup.append(this.$addItemWrap.detach().show()),this.$element.trigger("edited.fu.pillbox",{value:b.value,text:b.text})},removeBySelector:function(){var b=[].slice.call(arguments).slice(0),c=this;a.each(b,function(a,b){c.$pillGroup.find(b).remove()}),this._removePillTrigger({method:"removeBySelector",removedSelectors:b})},removeByValue:function(){var b=[].slice.call(arguments).slice(0),c=this;a.each(b,function(a,b){c.$pillGroup.find('> .pill[data-value="'+b+'"]').remove()}),this._removePillTrigger({method:"removeByValue",removedValues:b})},removeByText:function(){var b=[].slice.call(arguments).slice(0),c=this;a.each(b,function(a,b){c.$pillGroup.find('> .pill:contains("'+b+'")').remove()}),this._removePillTrigger({method:"removeByText",removedText:b})},truncate:function(b){var c,d,e,f,g,h=this;this.$element.removeClass("truncate"),this.$addItemWrap.removeClass("truncated"),this.$pillGroup.find(".pill").removeClass("truncated"),b&&(this.$element.addClass("truncate"),c=this.$element.width(),d=!1,e=0,f=this.$pillGroup.find(".pill").length,g=0,this.$pillGroup.find(".pill").each(function(){var b=a(this);d?b.addClass("truncated"):(e++,h.$moreCount.text(f-e),g+b.outerWidth(!0)+h.$addItemWrap.outerWidth(!0)<=c?g+=b.outerWidth(!0):(h.$moreCount.text(f-e+1),b.addClass("truncated"),d=!0))}),e===f&&this.$addItemWrap.addClass("truncated"))},inputFocus:function(){this.$element.find(".pillbox-add-item").focus()},getItemData:function(b,c){return a.extend({text:b.find("span:first").html()},b.data(),c)},_removeElement:function(a){a.el.remove(),delete a.el,this.$element.trigger("removed.fu.pillbox",a)},_removePillTrigger:function(a){this.$element.trigger("removed.fu.pillbox",a)},_generateObject:function(b){var c={};return a.each(b,function(a,b){c[b]=!0}),c},_openSuggestions:function(b,c){var d=a("<ul>");return this.callbackId!==b.timeStamp?!1:void(c.data&&c.data.length&&(a.each(c.data,function(b,c){var e=c.value?c.value:c.text,f=a('<li data-value="'+e+'">'+c.text+"</li>");c.attr&&f.data("attr",JSON.stringify(c.attr)),c.data&&f.data("data",c.data),d.append(f)}),this.$suggest.html("").append(d.children()),a(document.body).trigger("suggested.fu.pillbox",this.$suggest))) -},_closeSuggestions:function(){this.$suggest.html("").parent().removeClass("open")},_isSuggestionsOpen:function(){return this.$suggest.parent().hasClass("open")},_keySuggestions:function(a){var b,c=this.$suggest.find("li.pillbox-suggest-sel"),d=38===a.keyCode;a.preventDefault(),c.length?(b=d?c.prev():c.next(),b.length||(b=this.$suggest.find(d?"li:last":"li:first")),b&&(b.addClass("pillbox-suggest-sel"),c.removeClass("pillbox-suggest-sel"))):(c=this.$suggest.find("li:first"),c.addClass("pillbox-suggest-sel"))}},a.fn.pillbox=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.pillbox"),h="object"==typeof b&&b;g||f.data("fu.pillbox",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.pillbox.defaults={onAdd:void 0,onRemove:void 0,onKeyDown:void 0,edit:!1,readonly:-1,truncate:!1,acceptKeyCodes:[13,188]},a.fn.pillbox.Constructor=c,a.fn.pillbox.noConflict=function(){return a.fn.pillbox=b,this},a(document).on("mousedown.fu.pillbox.data-api","[data-initialize=pillbox]",function(b){var c=a(b.target).closest(".pillbox");c.data("fu.pillbox")||c.pillbox(c.data())}),a(function(){a("[data-initialize=pillbox]").each(function(){var b=a(this);b.data("fu.pillbox")||b.pillbox(b.data())})})}(a),function(a){var b=a.fn.repeater,c=function(b,c){var d,e,f=this;this.$element=a(b),this.$canvas=this.$element.find(".repeater-canvas"),this.$count=this.$element.find(".repeater-count"),this.$end=this.$element.find(".repeater-end"),this.$filters=this.$element.find(".repeater-filters"),this.$loader=this.$element.find(".repeater-loader"),this.$pageSize=this.$element.find(".repeater-itemization .selectlist"),this.$nextBtn=this.$element.find(".repeater-next"),this.$pages=this.$element.find(".repeater-pages"),this.$prevBtn=this.$element.find(".repeater-prev"),this.$primaryPaging=this.$element.find(".repeater-primaryPaging"),this.$search=this.$element.find(".repeater-search").find(".search"),this.$secondaryPaging=this.$element.find(".repeater-secondaryPaging"),this.$start=this.$element.find(".repeater-start"),this.$viewport=this.$element.find(".repeater-viewport"),this.$views=this.$element.find(".repeater-views"),this.eventStamp=(new Date).getTime()+(Math.floor(100*Math.random())+1),this.currentPage=0,this.currentView=null,this.infiniteScrollingCallback=function(){},this.infiniteScrollingCont=null,this.infiniteScrollingEnabled=!1,this.infiniteScrollingEnd=null,this.infiniteScrollingOptions={},this.lastPageInput=0,this.options=a.extend({},a.fn.repeater.defaults,c),this.pageIncrement=0,this.resizeTimeout={},this.staticHeight=-1===this.options.staticHeight?this.$element.attr("data-staticheight"):this.options.staticHeight,this.$filters.selectlist(),this.$pageSize.selectlist(),this.$primaryPaging.find(".combobox").combobox(),this.$search.search(),this.$filters.on("changed.fu.selectlist",function(a,b){f.$element.trigger("filtered.fu.repeater",b),f.render({clearInfinite:!0,pageIncrement:null})}),this.$nextBtn.on("click.fu.repeater",a.proxy(this.next,this)),this.$pageSize.on("changed.fu.selectlist",function(a,b){f.$element.trigger("pageSizeChanged.fu.repeater",b),f.render({pageIncrement:null})}),this.$prevBtn.on("click.fu.repeater",a.proxy(this.previous,this)),this.$primaryPaging.find(".combobox").on("changed.fu.combobox",function(a,b){f.$element.trigger("pageChanged.fu.repeater",[b.text,b]),f.pageInputChange(b.text)}),this.$search.on("searched.fu.search cleared.fu.search",function(a,b){f.$element.trigger("searchChanged.fu.repeater",b),f.render({clearInfinite:!0,pageIncrement:null})}),this.$secondaryPaging.on("blur.fu.repeater",function(){f.pageInputChange(f.$secondaryPaging.val())}),this.$secondaryPaging.on("keyup",function(a){13===a.keyCode&&f.pageInputChange(f.$secondaryPaging.val())}),this.$views.find("input").on("change.fu.repeater",a.proxy(this.viewChanged,this)),a(window).on("resize.fu.repeater."+this.eventStamp,function(){clearTimeout(f.resizeTimeout),f.resizeTimeout=setTimeout(function(){f.resize(),f.$element.trigger("resized.fu.repeater")},75)}),this.$loader.loader(),this.$loader.loader("pause"),-1!==this.options.defaultView?e=this.options.defaultView:(d=this.$views.find("label.active input"),e=d.length>0?d.val():"list"),this.initViews(function(){f.resize(),f.$element.trigger("resized.fu.repeater"),f.render({changeView:e})})};c.prototype={constructor:c,clear:function(b){var c=function(b){var d=[];b.children().each(function(){var b=a(this),e=b.attr("data-preserve");"deep"===e?(b.detach(),d.push(b)):"shallow"===e&&(c(b),b.detach(),d.push(b))}),b.empty(),b.append(d)};b=b||{},b.preserve?(!this.infiniteScrollingEnabled||b.clearInfinite)&&c(this.$canvas):this.$canvas.empty()},destroy:function(){var b;return this.$element.find("input").each(function(){a(this).attr("value",a(this).val())}),this.$canvas.empty(),b=this.$element[0].outerHTML,this.$element.find(".combobox").combobox("destroy"),this.$element.find(".selectlist").selectlist("destroy"),this.$element.find(".search").search("destroy"),this.infiniteScrollingEnabled&&a(this.infiniteScrollingCont).infinitescroll("destroy"),this.$element.remove(),a(window).off("resize.fu.repeater."+this.eventStamp),b},getDataOptions:function(b,c){var d,e,f={};b=b||{},f.filter=this.$filters.length>0?this.$filters.selectlist("selectedItem"):"all",f.view=this.currentView,this.infiniteScrollingEnabled||(f.pageSize=this.$pageSize.length>0?parseInt(this.$pageSize.selectlist("selectedItem").value,10):25),void 0!==b.pageIncrement&&(null===b.pageIncrement?this.currentPage=0:this.currentPage+=b.pageIncrement),f.pageIndex=this.currentPage,d=this.$search.length>0?this.$search.find("input").val():"",""!==d&&(f.search=d),e=a.fn.repeater.views[this.currentView]||{},e=e.dataOptions,e?e.call(this,f,function(a){c(a)}):c(f)},infiniteScrolling:function(a,b){var c,d,e=this.$element.find(".repeater-itemization"),f=this.$element.find(".repeater-pagination");b=b||{},a?(this.infiniteScrollingEnabled=!0,this.infiniteScrollingEnd=b.end,delete b.dataSource,delete b.end,this.infiniteScrollingOptions=b,e.hide(),f.hide()):(c=this.infiniteScrollingCont,d=c.data(),delete d.infinitescroll,c.off("scroll"),c.removeClass("infinitescroll"),this.infiniteScrollingCont=null,this.infiniteScrollingEnabled=!1,this.infiniteScrollingEnd=null,this.infiniteScrollingOptions={},e.show(),f.show())},infiniteScrollPaging:function(a){var b=this.infiniteScrollingEnd!==!0?this.infiniteScrollingEnd:void 0,c=a.page,d=a.pages;this.currentPage=void 0!==c?c:0/0,this.currentPage+1>=d&&this.infiniteScrollingCont.infinitescroll("end",b)},initInfiniteScrolling:function(){var b,c,d=this.$canvas.find('[data-infinite="true"]:first');d=d.length<1?this.$canvas:d,d.data("fu.infinitescroll")?d.infinitescroll("enable"):(c=this,b=a.extend({},this.infiniteScrollingOptions),b.dataSource=function(a,b){c.infiniteScrollingCallback=b,c.render({pageIncrement:1})},d.infinitescroll(b),this.infiniteScrollingCont=d)},initViews:function(b){var c,d,e=[],f=function(a){var c=function(){a++,d>a?f(a):b()};e[a].initialize?e[a].initialize.call(this,{},function(){c()}):c()};for(c in a.fn.repeater.views)e.push(a.fn.repeater.views[c]);d=e.length,d>0?f(0):b()},itemization:function(a){this.$count.html(a.count||""),this.$end.html(a.end||""),this.$start.html(a.start||"")},next:function(){var a="disabled";this.$nextBtn.attr(a,a),this.$prevBtn.attr(a,a),this.pageIncrement=1,this.$element.trigger("nextClicked.fu.repeater"),this.render({pageIncrement:this.pageIncrement})},pageInputChange:function(a){var b;a!==this.lastPageInput&&(this.lastPageInput=a,a=parseInt(a,10)-1,b=a-this.currentPage,this.$element.trigger("pageChanged.fu.repeater",a),this.render({pageIncrement:b}))},pagination:function(a){var b,c,d,e="active",f="disabled",g=a.page,h=a.pages;if(this.currentPage=void 0!==g?g:0/0,this.$primaryPaging.removeClass(e),this.$secondaryPaging.removeClass(e),h<=this.options.dropPagingCap){for(this.$primaryPaging.addClass(e),b=this.$primaryPaging.find(".dropdown-menu"),b.empty(),c=0;h>c;c++)d=c+1,b.append('<li data-value="'+d+'"><a href="#">'+d+"</a></li>");this.$primaryPaging.find("input.form-control").val(this.currentPage+1)}else this.$secondaryPaging.addClass(e),this.$secondaryPaging.val(this.currentPage+1);this.lastPageInput=this.currentPage+1+"",this.$pages.html(h),this.currentPage+1<h?this.$nextBtn.removeAttr(f):this.$nextBtn.attr(f,f),this.currentPage-1>=0?this.$prevBtn.removeAttr(f):this.$prevBtn.attr(f,f),0!==this.pageIncrement&&(this.pageIncrement>0?this.$nextBtn.is(":disabled")?this.$prevBtn.focus():this.$nextBtn.focus():this.$prevBtn.is(":disabled")?this.$nextBtn.focus():this.$prevBtn.focus())},previous:function(){var a="disabled";this.$nextBtn.attr(a,a),this.$prevBtn.attr(a,a),this.pageIncrement=-1,this.$element.trigger("previousClicked.fu.repeater"),this.render({pageIncrement:this.pageIncrement})},render:function(b){var c,d=this,e=!1,f=a.fn.repeater.views[d.currentView]||{},g=function(){var a=function(){(!d.infiniteScrollingEnabled||d.infiniteScrollingEnabled&&e)&&d.$loader.show().loader("play"),d.getDataOptions(b,function(a){d.options.dataSource(a,function(a){var c=f.renderer;d.infiniteScrollingEnabled?d.infiniteScrollingCallback({}):(d.itemization(a),d.pagination(a)),c&&d.runRenderer(d.$canvas,c,a,function(){d.infiniteScrollingEnabled&&((e||b.clearInfinite)&&d.initInfiniteScrolling(),d.infiniteScrollPaging(a,b)),d.$loader.hide().loader("pause"),d.$element.trigger("loaded.fu.repeater")})})})};b.preserve=void 0!==b.preserve?b.preserve:!e,d.clear(b),!e&&f.cleared?f.cleared.call(d,{},function(){a()}):a()};b=b||{},b.changeView&&this.currentView!==b.changeView?(c=this.currentView,this.currentView=b.changeView,this.$element.attr("data-currentview",this.currentView),e=!0,this.infiniteScrollingEnabled&&d.infiniteScrolling(!1),f=a.fn.repeater.views[d.currentView]||{},f.selected?f.selected.call(this,{prevView:c},function(){g()}):g()):g()},resize:function(){var b,c,d=this.staticHeight,e=a.fn.repeater.views[this.currentView]||{};void 0!==d?(this.$canvas.addClass("scrolling"),c={bottom:this.$viewport.css("margin-bottom"),top:this.$viewport.css("margin-top")},b=("true"===d||d===!0?this.$element.height():parseInt(d,10))-this.$element.find(".repeater-header").outerHeight()-this.$element.find(".repeater-footer").outerHeight()-("auto"===c.bottom?0:parseInt(c.bottom,10))-("auto"===c.top?0:parseInt(c.top,10)),this.$viewport.outerHeight(b)):this.$canvas.removeClass("scrolling"),e.resize&&e.resize.call(this,{height:this.$element.outerHeight(),width:this.$element.outerWidth()},function(){})},runRenderer:function(b,c,d,e){var f,g,h,i,j=this,k=!1,l=function(a){var f={container:b,data:d};c.repeat&&(f.subset=g,f.index=a),g.length<1?e():m(f,function(){a++,a<g.length?l(a):e()})},m=function(e,f){var g="",h={before:function(a){a&&a.skipNested===!0&&(k=!0),i("render",e)},render:function(c){var d=c&&c.action?c.action:"append";c&&void 0!==c.item&&(g=a(c.item),g.length<1&&(g=c.item),"none"!==d&&b[d](g),e.item=g),c&&c.skipNested===!0&&(k=!0),i("after",e)},after:function(f){var l,m=function(a,b){j.runRenderer(a,c.nested[b],d,function(){b++,b<c.nested.length?m(a,b):i("complete",e)})};f&&f.skipNested===!0&&(k=!0),c.nested&&!k?(l=a(g),l="true"===l.attr("data-container")?l:l.find('[data-container="true"]:first'),l.length<1&&(l=b),m(l,0)):h.complete(null)},complete:function(){f&&f()}},i=function(b,d){d=a.extend({},d),c[b]?c[b].call(j,d,h[b]):h[b](null)};i("before",e)};if(c.repeat)for(f=c.repeat.split("."),"data"===f[0]||"this"===f[0]?(g="this"===f[0]?this:d,f.shift()):(f=[],g=[""]),h=0,i=f.length;i>h;h++)g=g[f[h]];else g=[""];l(0)},viewChanged:function(b){var c=a(b.target),d=c.val();this.$element.trigger("viewChanged.fu.repeater",d),this.render({changeView:d,pageIncrement:null})}},a.fn.repeater=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.repeater"),h="object"==typeof b&&b;g||f.data("fu.repeater",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.repeater.defaults={dataSource:function(){},defaultView:-1,dropPagingCap:10,staticHeight:-1},a.fn.repeater.views={},a.fn.repeater.Constructor=c,a.fn.repeater.noConflict=function(){return a.fn.repeater=b,this}}(a),function(a){a.fn.repeater&&(a.fn.repeater.Constructor.prototype.list_clearSelectedItems=function(){this.$canvas.find(".repeater-list-check").remove(),this.$canvas.find(".repeater-list table tbody tr.selected").removeClass("selected")},a.fn.repeater.Constructor.prototype.list_getSelectedItems=function(){var b=[];return this.$canvas.find(".repeater-list table tbody tr.selected").each(function(){var c=a(this);b.push({data:c.data("item_data"),element:c})}),b},a.fn.repeater.Constructor.prototype.list_positionHeadings=function(){var b=this.$element.find(".repeater-list-wrapper"),c=b.offset().left,d=b.scrollLeft();b.find(".repeater-list-heading").each(d>0?function(){var b=a(this),d=b.parents("th:first").offset().left-c+"px";b.addClass("shifted").css("left",d)}:function(){a(this).removeClass("shifted").css("left","")})},a.fn.repeater.Constructor.prototype.list_setSelectedItems=function(b,c){var d,e,f,g,h=this.options.list_selectable,i=this,j=function(){f=a(this),d=f.data("item_data")||{},d[b[e].property]===b[e].value&&k(f,b[e].selected)},k=function(a,b){b=void 0!==b?b:!0,b?(c||"multi"===h||i.list_clearSelectedItems(),a.hasClass("selected")||(a.addClass("selected"),a.find("td:first").prepend('<div class="repeater-list-check"><span class="glyphicon glyphicon-ok"></span></div>'))):(a.find(".repeater-list-check").remove(),a.removeClass("selected"))};for(a.isArray(b)||(b=[b]),g=c===!0||"multi"===h?b.length:h&&b.length>0?1:0,e=0;g>e;e++)void 0!==b[e].index?(f=this.$canvas.find(".repeater-list table tbody tr:nth-child("+(b[e].index+1)+")"),f.length>0&&k(f,b[e].selected)):void 0!==b[e].property&&void 0!==b[e].value&&this.$canvas.find(".repeater-list table tbody tr").each(j)},a.fn.repeater.Constructor.prototype.list_sizeHeadings=function(){var b=this.$element.find(".repeater-list table");b.find("thead th").each(function(){var b=a(this),c=b.find(".repeater-list-heading");c.outerHeight(b.outerHeight()),c.outerWidth(b.outerWidth())})},a.fn.repeater.defaults=a.extend({},a.fn.repeater.defaults,{list_columnRendered:null,list_columnSizing:!0,list_columnSyncing:!0,list_infiniteScroll:!1,list_noItemsHTML:"",list_selectable:!1,list_sortClearing:!1,list_rowRendered:null}),a.fn.repeater.views.list={cleared:function(a,b){this.options.list_columnSyncing&&this.list_sizeHeadings(),b()},dataOptions:function(a,b){this.list_sortDirection&&(a.sortDirection=this.list_sortDirection),this.list_sortProperty&&(a.sortProperty=this.list_sortProperty),b(a)},initialize:function(a,b){this.list_sortDirection=null,this.list_sortProperty=null,b()},selected:function(a,b){var c,d=this.options.list_infiniteScroll;this.list_firstRender=!0,this.$loader.addClass("noHeader"),d&&(c="object"==typeof d?d:{},this.infiniteScrolling(!0,c)),b()},resize:function(a,b){this.options.list_columnSyncing&&this.list_sizeHeadings(),b()},renderer:{complete:function(a,b){this.options.list_columnSyncing&&(this.list_sizeHeadings(),this.list_positionHeadings()),b()},render:function(b,c){var d,e=this.$element.find(".repeater-list"),f=this;e.length>0?c({action:"none",item:e}):(d=a('<div class="repeater-list" data-preserve="shallow"><div class="repeater-list-wrapper" data-infinite="true" data-preserve="shallow"><table aria-readonly="true" class="table" data-container="true" data-preserve="shallow" role="grid"></table></div></div>'),d.find(".repeater-list-wrapper").on("scroll.fu.repeaterList",function(){f.options.list_columnSyncing&&f.list_positionHeadings()}),c({item:d}))},nested:[{complete:function(b,c){var d,e,f,g,h=[],i=this;if(!this.options.list_columnSizing||this.list_columnsSame)c();else{if(d=0,g=0,b.item.find("th").each(function(){var b,c=a(this),e=0===c.next("th").length;void 0!==i.list_columns[d].width?(b=i.list_columns[d].width,c.outerWidth(b),g+=c.outerWidth(),e?c.outerWidth(""):i.list_columns[d]._auto_width=b):h.push({col:c,index:d,last:e}),d++}),e=h.length,e>0)for(f=Math.floor((this.$canvas.width()-g)/e),d=0;e>d;d++)h[d].last||(h[d].col.outerWidth(f),this.list_columns[h[d].index]._auto_width=f);c()}},render:function(a,b){var c=function(a,b){var c,d,e;if(!a)return!0;if(!b)return!1;for(c=0,e=b.length;e>c;c++){if(!a[c])return!0;for(d in b[c])if(a[c][d]!==b[c][d])return!0}return!1};this.list_firstRender||c(this.list_columns,a.data.columns)?(this.$element.find(".repeater-list-header").remove(),this.list_columns=a.data.columns,this.list_columnsSame=!1,this.list_firstRender=!1,this.$loader.removeClass("noHeader"),b({item:'<thead data-preserve="deep"><tr data-container="true"></tr></thead>'})):(this.list_columnsSame=!0,b({skipNested:!0}))},nested:[{render:function(b,c){var d,e,f,g,h,i="glyphicon-chevron-down",j=".glyphicon.rlc:first",k="glyphicon-chevron-up",l=a('<div class="repeater-list-heading"><span class="glyphicon rlc"></span></div>'),m=b.index,n=a("<th></th>"),o=this,p=b.subset;l.prepend(b.subset[b.index].label),n.html(l.html()).find("[id]").removeAttr("id"),n.append(l),d=n.add(l),g=l.find(j),h=g.add(n.find(j)),e=p[m].className,void 0!==e&&d.addClass(e),f=p[m].sortable,f&&(d.addClass("sortable"),l.on("click.fu.repeaterList",function(){o.list_sortProperty="string"==typeof f?f:p[m].property,l.hasClass("sorted")?g.hasClass(k)?(h.removeClass(k).addClass(i),o.list_sortDirection="desc"):o.options.list_sortClearing?(d.removeClass("sorted"),h.removeClass(i),o.list_sortDirection=null,o.list_sortProperty=null):(h.removeClass(i).addClass(k),o.list_sortDirection="asc"):(b.container.find("th, .repeater-list-heading").removeClass("sorted"),h.removeClass(i).addClass(k),o.list_sortDirection="asc",d.addClass("sorted")),o.render({clearInfinite:!0,pageIncrement:null})})),("asc"===p[m].sortDirection||"desc"===p[m].sortDirection)&&(b.container.find("th, .repeater-list-heading").removeClass("sorted"),d.addClass("sortable sorted"),"asc"===p[m].sortDirection?(h.addClass(k),this.list_sortDirection="asc"):(h.addClass(i),this.list_sortDirection="desc"),this.list_sortProperty="string"==typeof f?f:p[m].property),c({item:n})},repeat:"data.columns"}]},{render:function(b,c){var d,e=a('<tbody data-container="true"></tbody>'),f={};b.data.items.length<1&&(f.skipNested=!0,d=a('<tr class="empty"><td colspan="'+this.list_columns.length+'"></td></tr>'),d.find("td").append(this.options.list_noItemsHTML),e.append(d)),f.item=e,c(f)},nested:[{complete:function(a,b){var c={container:a.container,rowData:a.subset[a.index]};void 0!==a.item&&(c.item=a.item),this.options.list_rowRendered?this.options.list_rowRendered(c,function(){b()}):b()},render:function(b,c){var d=a('<tr data-container="true"></tr>'),e=this;this.options.list_selectable&&(d.addClass("selectable"),d.attr("tabindex",0),d.data("item_data",b.subset[b.index]),d.on("click.fu.repeaterList",function(){var b=a(this);b.hasClass("selected")?(b.removeClass("selected"),b.find(".repeater-list-check").remove(),e.$element.trigger("deselected.fu.repeaterList",b)):("multi"!==e.options.list_selectable&&(e.$canvas.find(".repeater-list-check").remove(),e.$canvas.find(".repeater-list tbody tr.selected").each(function(){a(this).removeClass("selected"),e.$element.trigger("deselected.fu.repeaterList",a(this))})),b.addClass("selected"),b.find("td:first").prepend('<div class="repeater-list-check"><span class="glyphicon glyphicon-ok"></span></div>'),e.$element.trigger("selected.fu.repeaterList",b))}),d.keyup(function(a){13===a.keyCode&&d.trigger("clicked.fu.repeaterList")})),this.list_curRowIndex=b.index,c({item:d})},repeat:"data.items",nested:[{after:function(a,b){var c={container:a.container,columnAttr:a.subset[a.index].property,rowData:a.data.items[this.list_curRowIndex]};void 0!==a.item&&(c.item=a.item),this.options.list_columnRendered?this.options.list_columnRendered(c,function(){b()}):b()},render:function(b,c){var d=b.subset[b.index].className,e=b.data.items[this.list_curRowIndex][b.subset[b.index].property],f=a("<td></td>"),g=b.subset[b.index]._auto_width;f.addClass(void 0!==d?d:"").append(e),void 0!==g&&f.outerWidth(g),c({item:f})},repeat:"this.list_columns"}]}]}]}})}(a),function(a){a.fn.repeater&&(a.fn.repeater.Constructor.prototype.thumbnail_clearSelectedItems=function(){this.$canvas.find(".repeater-thumbnail-cont .repeater-thumbnail.selected").removeClass("selected")},a.fn.repeater.Constructor.prototype.thumbnail_getSelectedItems=function(){var b=[];return this.$canvas.find(".repeater-thumbnail-cont .repeater-thumbnail.selected").each(function(){b.push(a(this))}),b},a.fn.repeater.Constructor.prototype.thumbnail_setSelectedItems=function(b,c){var d,e,f,g=this.options.thumbnail_selectable,h=this,i=function(){e=a(this),e.is(b[d].selector)&&j(e,b[d].selected)},j=function(a,b){b=void 0!==b?b:!0,b?(c||"multi"===g||h.thumbnail_clearSelectedItems(),a.addClass("selected")):a.removeClass("selected")};for(a.isArray(b)||(b=[b]),f=c===!0||"multi"===g?b.length:g&&b.length>0?1:0,d=0;f>d;d++)void 0!==b[d].index?(e=this.$canvas.find(".repeater-thumbnail-cont .repeater-thumbnail:nth-child("+(b[d].index+1)+")"),e.length>0&&j(e,b[d].selected)):b[d].selector&&this.$canvas.find(".repeater-thumbnail-cont .repeater-thumbnail").each(i)},a.fn.repeater.defaults=a.extend({},a.fn.repeater.defaults,{thumbnail_infiniteScroll:!1,thumbnail_itemRendered:null,thumbnail_selectable:!1,thumbnail_template:'<div class="thumbnail repeater-thumbnail"><img height="75" src="{{src}}" width="65"><span>{{name}}</span></div>'}),a.fn.repeater.views.thumbnail={selected:function(a,b){var c,d=this.options.thumbnail_infiniteScroll;d&&(c="object"==typeof d?d:{},this.infiniteScrolling(!0,c)),b({})},renderer:{render:function(b,c){var d,e=this.$canvas.find(".repeater-thumbnail-cont"),f={};e.length>0?f.action="none":e=a('<div class="clearfix repeater-thumbnail-cont" data-container="true" data-infinite="true" data-preserve="shallow"></div>'),f.item=e,b.data.items.length<1?(f.skipNested=!0,d=a('<div class="empty"></div>'),d.append(this.options.thumbnail_noItemsHTML),e.append(d)):e.find(".empty:first").remove(),c(f)},nested:[{after:function(b,c){var d,e={container:b.container,itemData:b.subset[b.index]},f=this.options.thumbnail_selectable,g="selected",h=this;void 0!==b.item&&(e.item=b.item,f&&(d=a(e.item),d.addClass("selectable"),d.on("click",function(){d.hasClass(g)?(d.removeClass(g),h.$element.trigger("deselected.fu.repeaterThumbnail",d)):("multi"!==f&&h.$canvas.find(".repeater-thumbnail-cont .repeater-thumbnail.selected").each(function(){var b=a(this);b.removeClass(g),h.$element.trigger("deselected.fu.repeaterThumbnail",b)}),d.addClass(g),h.$element.trigger("selected.fu.repeaterThumbnail",d))}))),this.options.thumbnail_itemRendered?this.options.thumbnail_itemRendered(e,function(){c()}):c()},render:function(b,c){var d=b.subset[b.index],e=function(b){for(var c=!1,e=function(){var e,f,g;f=b.indexOf("{{"),e=b.indexOf("}}",f+2),f>-1&&e>-1?(g=a.trim(b.substring(f+2,e)),g=void 0!==d[g]?d[g]:"",b=b.substring(0,f)+g+b.substring(e+2)):c=!0};!c&&b.search("{{")>=0;)e(b);return b};c({item:e(this.options.thumbnail_template)})},repeat:"data.items"}]}})}(a),function(a){var b=a.fn.scheduler,c=function(b,c){var d=this;this.$element=a(b),this.options=a.extend({},a.fn.scheduler.defaults,c),this.$startDate=this.$element.find(".start-datetime .start-date"),this.$startTime=this.$element.find(".start-datetime .start-time"),this.$timeZone=this.$element.find(".timezone-container .timezone"),this.$repeatIntervalPanel=this.$element.find(".repeat-every-panel"),this.$repeatIntervalSelect=this.$element.find(".repeat-options"),this.$repeatIntervalSpinbox=this.$element.find(".repeat-every"),this.$repeatIntervalTxt=this.$element.find(".repeat-every-text"),this.$end=this.$element.find(".repeat-end"),this.$endSelect=this.$end.find(".end-options"),this.$endAfter=this.$end.find(".end-after"),this.$endDate=this.$end.find(".end-on-date"),this.$recurrencePanels=this.$element.find(".repeat-panel"),this.$repeatIntervalSelect.selectlist(),this.$element.find(".selectlist").selectlist(),this.$startDate.datepicker(),this.$startTime.combobox(),""===this.$startTime.find("input").val()&&this.$startTime.combobox("selectByIndex",0),this.$repeatIntervalSpinbox.spinbox("0"===this.$repeatIntervalSpinbox.find("input").val()?{value:1,min:1}:{min:1}),this.$endAfter.spinbox({value:1,min:1}),this.$endDate.datepicker(),this.$element.find(".radio-custom").radio(),this.$repeatIntervalSelect.on("changed.fu.selectlist",a.proxy(this.repeatIntervalSelectChanged,this)),this.$endSelect.on("changed.fu.selectlist",a.proxy(this.endSelectChanged,this)),this.$element.find(".repeat-days-of-the-week .btn-group .btn").on("change.fu.scheduler",function(a,b){d.changed(a,b,!0)}),this.$element.find(".combobox").on("changed.fu.combobox",a.proxy(this.changed,this)),this.$element.find(".datepicker").on("changed.fu.datepicker",a.proxy(this.changed,this)),this.$element.find(".selectlist").on("changed.fu.selectlist",a.proxy(this.changed,this)),this.$element.find(".spinbox").on("changed.fu.spinbox",a.proxy(this.changed,this)),this.$element.find(".repeat-monthly .radio, .repeat-yearly .radio").on("change.fu.scheduler",a.proxy(this.changed,this))};c.prototype={constructor:c,destroy:function(){var b;return this.$element.find("input").each(function(){a(this).attr("value",a(this).val())}),this.$element.find(".datepicker .calendar").empty(),b=this.$element[0].outerHTML,this.$element.find(".combobox").combobox("destroy"),this.$element.find(".datepicker").datepicker("destroy"),this.$element.find(".selectlist").selectlist("destroy"),this.$element.find(".spinbox").spinbox("destroy"),this.$element.find("[type=radio]").radio("destroy"),this.$element.remove(),b},changed:function(b,c,d){d||b.stopPropagation(),this.$element.trigger("changed.fu.scheduler",{data:void 0!==c?c:a(b.currentTarget).data(),originalEvent:b,value:this.getValue()})},disable:function(){this.toggleState("disable")},enable:function(){this.toggleState("enable")},endSelectChanged:function(a,b){var c,d;b?d=b.value:(c=this.$endSelect.selectlist("selectedItem"),d=c.value),this.$endAfter.parent().addClass("hide"),this.$endAfter.parent().attr("aria-hidden","true"),this.$endDate.parent().addClass("hide"),this.$endDate.parent().attr("aria-hidden","true"),"after"===d?(this.$endAfter.parent().removeClass("hide"),this.$endAfter.parent().attr("aria-hidden","false")):"date"===d&&(this.$endDate.parent().removeClass("hide"),this.$endDate.parent().attr("aria-hidden","false"))},getValue:function(){var b,c=this.$repeatIntervalSpinbox.spinbox("value"),d="",e=this.$repeatIntervalSelect.selectlist("selectedItem").value,f=this.$startTime.combobox("selectedItem").text.toLowerCase(),g=this.$timeZone.selectlist("selectedItem");b=function(a,b){var c,d="";return d+=a.getFullYear(),d+=b,c=a.getMonth()+1,d+=10>c?"0"+c:c,d+=b,c=a.getDate(),d+=10>c?"0"+c:c};var h,i,j,k,l,m,n,o;n=""+b(this.$startDate.datepicker("getDate"),"-"),n+="T",j=f.search("am")>=0,k=f.search("pm")>=0,f=a.trim(f.replace(/am/g,"").replace(/pm/g,"")).split(":"),f[0]=parseInt(f[0],10),f[1]=parseInt(f[1],10),j&&f[0]>11?f[0]=0:k&&f[0]<12&&(f[0]+=12),n+=f[0]<10?"0"+f[0]:f[0],n+=":",n+=f[1]<10?"0"+f[1]:f[1],n+="+00:00"===g.offset?"Z":g.offset,"none"===e?d="FREQ=DAILY;INTERVAL=1;COUNT=1;":"hourly"===e?(d="FREQ=HOURLY;",d+="INTERVAL="+c+";"):"daily"===e?(d+="FREQ=DAILY;",d+="INTERVAL="+c+";"):"weekdays"===e?(d+="FREQ=DAILY;",d+="BYDAY=MO,TU,WE,TH,FR;",d+="INTERVAL=1;"):"weekly"===e?(i=[],this.$element.find(".repeat-days-of-the-week .btn-group input:checked").each(function(){i.push(a(this).data().value)}),d+="FREQ=WEEKLY;",d+="BYDAY="+i.join(",")+";",d+="INTERVAL="+c+";"):"monthly"===e?(d+="FREQ=MONTHLY;",d+="INTERVAL="+c+";",o=this.$element.find("input[name=repeat-monthly]:checked").val(),"bymonthday"===o?(h=parseInt(this.$element.find(".repeat-monthly-date .selectlist").selectlist("selectedItem").text,10),d+="BYMONTHDAY="+h+";"):"bysetpos"===o&&(i=this.$element.find(".month-days").selectlist("selectedItem").value,m=this.$element.find(".month-day-pos").selectlist("selectedItem").value,d+="BYDAY="+i+";",d+="BYSETPOS="+m+";")):"yearly"===e&&(d+="FREQ=YEARLY;",o=this.$element.find("input[name=repeat-yearly]:checked").val(),"bymonthday"===o?(l=this.$element.find(".repeat-yearly-date .year-month").selectlist("selectedItem").value,h=this.$element.find(".year-month-day").selectlist("selectedItem").text,d+="BYMONTH="+l+";",d+="BYMONTHDAY="+h+";"):"bysetpos"===o&&(i=this.$element.find(".year-month-days").selectlist("selectedItem").value,m=this.$element.find(".year-month-day-pos").selectlist("selectedItem").value,l=this.$element.find(".repeat-yearly-day .year-month").selectlist("selectedItem").value,d+="BYDAY="+i+";",d+="BYSETPOS="+m+";",d+="BYMONTH="+l+";"));var p=this.$endSelect.selectlist("selectedItem").value,q="";"none"!==e&&("after"===p?q="COUNT="+this.$endAfter.spinbox("value")+";":"date"===p&&(q="UNTIL="+b(this.$endDate.datepicker("getDate"),"")+";")),d+=q;var r={startDateTime:n,timeZone:{name:g.name,offset:g.offset},recurrencePattern:d};return r},repeatIntervalSelectChanged:function(a,b){var c,d,e;switch(b?(d=b.value,e=b.text):(c=this.$repeatIntervalSelect.selectlist("selectedItem"),d=c.value,e=c.text),this.$repeatIntervalTxt.text(e),d.toLowerCase()){case"hourly":case"daily":case"weekly":case"monthly":this.$repeatIntervalPanel.removeClass("hide"),this.$repeatIntervalPanel.attr("aria-hidden","false");break;default:this.$repeatIntervalPanel.addClass("hide"),this.$repeatIntervalPanel.attr("aria-hidden","true")}this.$recurrencePanels.addClass("hide"),this.$recurrencePanels.attr("aria-hidden","true"),this.$element.find(".repeat-"+d).removeClass("hide"),this.$element.find(".repeat-"+d).attr("aria-hidden","false"),"none"===d?(this.$end.addClass("hide"),this.$end.attr("aria-hidden","true")):(this.$end.removeClass("hide"),this.$end.attr("aria-hidden","false"))},setValue:function(b){var c,d,e,f,g,h,i,j;if(b.startDateTime&&(j=b.startDateTime.split("T"),this.$startDate.datepicker("setDate",j[0]),j[1]&&(j[1]=j[1].split(":"),c=parseInt(j[1][0],10),g=j[1][1]?parseInt(j[1][1].split("+")[0].split("-")[0].split("Z")[0],10):0,h=12>c?"AM":"PM",0===c?c=12:c>12&&(c-=12),g=10>g?"0"+g:g,j=c+":"+g+" "+h,this.$startTime.find("input").val(j),this.$startTime.combobox("selectByText",j))),e="li[data",b.timeZone?(e+="string"==typeof b.timeZone?'-name="'+b.timeZone:b.timeZone.name?'-name="'+b.timeZone.name:'-offset="'+b.timeZone.offset,e+='"]',this.$timeZone.selectlist("selectBySelector",e)):b.startDateTime&&(j=b.startDateTime.split("T")[1],j=j?j.search(/\+/)>-1?"+"+a.trim(j.split("+")[1]):j.search(/\-/)>-1?"-"+a.trim(j.split("-")[1]):"+00:00":"+00:00",e+='-offset="'+j+'"]',this.$timeZone.selectlist("selectBySelector",e)),b.recurrencePattern){for(i={},j=b.recurrencePattern.toUpperCase().split(";"),d=0,f=j.length;f>d;d++)""!==j[d]&&(e=j[d].split("="),i[e[0]]=e[1]);if("DAILY"===i.FREQ)e="MO,TU,WE,TH,FR"===i.BYDAY?"weekdays":"1"===i.INTERVAL&&"1"===i.COUNT?"none":"daily";else if("HOURLY"===i.FREQ)e="hourly";else if("WEEKLY"===i.FREQ){if(i.BYDAY)for(e=this.$element.find(".repeat-days-of-the-week .btn-group"),e.find("label").removeClass("active"),j=i.BYDAY.split(","),d=0,f=j.length;f>d;d++)e.find('input[data-value="'+j[d]+'"]').parent().addClass("active");e="weekly"}else"MONTHLY"===i.FREQ?(this.$element.find(".repeat-monthly input").removeAttr("checked").removeClass("checked"),this.$element.find(".repeat-monthly label.radio-custom").removeClass("checked"),i.BYMONTHDAY?(j=this.$element.find(".repeat-monthly-date"),j.find("input").addClass("checked").attr("checked","checked"),j.find("label.radio-custom").addClass("checked"),j.find(".selectlist").selectlist("selectByValue",i.BYMONTHDAY)):i.BYDAY&&(j=this.$element.find(".repeat-monthly-day"),j.find("input").addClass("checked").attr("checked","checked"),j.find("label.radio-custom").addClass("checked"),i.BYSETPOS&&j.find(".month-day-pos").selectlist("selectByValue",i.BYSETPOS),j.find(".month-days").selectlist("selectByValue",i.BYDAY)),e="monthly"):"YEARLY"===i.FREQ?(this.$element.find(".repeat-yearly input").removeAttr("checked").removeClass("checked"),this.$element.find(".repeat-yearly label.radio-custom").removeClass("checked"),i.BYMONTHDAY?(j=this.$element.find(".repeat-yearly-date"),j.find("input").addClass("checked").attr("checked","checked"),j.find("label.radio-custom").addClass("checked"),i.BYMONTH&&j.find(".year-month").selectlist("selectByValue",i.BYMONTH),j.find(".year-month-day").selectlist("selectByValue",i.BYMONTHDAY)):i.BYSETPOS&&(j=this.$element.find(".repeat-yearly-day"),j.find("input").addClass("checked").attr("checked","checked"),j.find("label.radio-custom").addClass("checked"),j.find(".year-month-day-pos").selectlist("selectByValue",i.BYSETPOS),i.BYDAY&&j.find(".year-month-days").selectlist("selectByValue",i.BYDAY),i.BYMONTH&&j.find(".year-month").selectlist("selectByValue",i.BYMONTH)),e="yearly"):e="none"; -i.COUNT?(this.$endAfter.spinbox("value",parseInt(i.COUNT,10)),this.$endSelect.selectlist("selectByValue","after")):i.UNTIL&&(j=i.UNTIL,8===j.length&&(j=j.split(""),j.splice(4,0,"-"),j.splice(7,0,"-"),j=j.join("")),this.$endDate.datepicker("setDate",j),this.$endSelect.selectlist("selectByValue","date")),this.endSelectChanged(),i.INTERVAL&&this.$repeatIntervalSpinbox.spinbox("value",parseInt(i.INTERVAL,10)),this.$repeatIntervalSelect.selectlist("selectByValue",e),this.repeatIntervalSelectChanged()}},toggleState:function(a){this.$element.find(".combobox").combobox(a),this.$element.find(".datepicker").datepicker(a),this.$element.find(".selectlist").selectlist(a),this.$element.find(".spinbox").spinbox(a),this.$element.find("[type=radio]").radio(a),a="disable"===a?"addClass":"removeClass",this.$element.find(".repeat-days-of-the-week .btn-group")[a]("disabled")},value:function(a){return a?this.setValue(a):this.getValue()}},a.fn.scheduler=function(b){var d,e=Array.prototype.slice.call(arguments,1),f=this.each(function(){var f=a(this),g=f.data("fu.scheduler"),h="object"==typeof b&&b;g||f.data("fu.scheduler",g=new c(this,h)),"string"==typeof b&&(d=g[b].apply(g,e))});return void 0===d?f:d},a.fn.scheduler.defaults={},a.fn.scheduler.Constructor=c,a.fn.scheduler.noConflict=function(){return a.fn.scheduler=b,this},a(document).on("mousedown.fu.scheduler.data-api","[data-initialize=scheduler]",function(b){var c=a(b.target).closest(".scheduler");c.data("fu.scheduler")||c.scheduler(c.data())}),a(function(){a("[data-initialize=scheduler]").each(function(){var b=a(this);b.data("scheduler")||b.scheduler(b.data())})})}(a)}); /*! FullCalendar v5.10.1 Docs & License: https://fullcalendar.io/ @@ -2081,7 +2067,9 @@ return (function () { getCacheBusterParam: false, globalViewTransitions: false, methodsThatUseUrlParams: ["get"], - selfRequestsOnly: false + selfRequestsOnly: false, + ignoreTitle: false, + scrollIntoViewOnBoost: true }, parseInterval:parseInterval, _:internalEval, @@ -2093,7 +2081,7 @@ return (function () { sock.binaryType = htmx.config.wsBinaryType; return sock; }, - version: "1.9.6" + version: "1.9.9" }; /** @type {import("./htmx").HtmxInternalApi} */ @@ -2603,8 +2591,12 @@ return (function () { return [closest(elt, normalizeSelector(selector.substr(8)))]; } else if (selector.indexOf("find ") === 0) { return [find(elt, normalizeSelector(selector.substr(5)))]; + } else if (selector === "next") { + return [elt.nextElementSibling] } else if (selector.indexOf("next ") === 0) { return [scanForwardQuery(elt, normalizeSelector(selector.substr(5)))]; + } else if (selector === "previous") { + return [elt.previousElementSibling] } else if (selector.indexOf("previous ") === 0) { return [scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)))]; } else if (selector === 'document') { @@ -3147,6 +3139,8 @@ return (function () { var SYMBOL_CONT = /[_$a-zA-Z0-9]/; var STRINGISH_START = ['"', "'", "/"]; var NOT_WHITESPACE = /[^\s]/; + var COMBINED_SELECTOR_START = /[{(]/; + var COMBINED_SELECTOR_END = /[})]/; function tokenizeString(str) { var tokens = []; var position = 0; @@ -3235,6 +3229,18 @@ return (function () { return result; } + function consumeCSSSelector(tokens) { + var result; + if (tokens.length > 0 && COMBINED_SELECTOR_START.test(tokens[0])) { + tokens.shift(); + result = consumeUntil(tokens, COMBINED_SELECTOR_END).trim(); + tokens.shift(); + } else { + result = consumeUntil(tokens, WHITESPACE_OR_COMMA); + } + return result; + } + var INPUT_SELECTOR = 'input, textarea, select'; /** @@ -3283,27 +3289,33 @@ return (function () { triggerSpec.delay = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA)); } else if (token === "from" && tokens[0] === ":") { tokens.shift(); - var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA); - if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") { - tokens.shift(); - from_arg += - " " + - consumeUntil( - tokens, - WHITESPACE_OR_COMMA - ); + if (COMBINED_SELECTOR_START.test(tokens[0])) { + var from_arg = consumeCSSSelector(tokens); + } else { + var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA); + if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") { + tokens.shift(); + var selector = consumeCSSSelector(tokens); + // `next` and `previous` allow a selector-less syntax + if (selector.length > 0) { + from_arg += " " + selector; + } + } } triggerSpec.from = from_arg; } else if (token === "target" && tokens[0] === ":") { tokens.shift(); - triggerSpec.target = consumeUntil(tokens, WHITESPACE_OR_COMMA); + triggerSpec.target = consumeCSSSelector(tokens); } else if (token === "throttle" && tokens[0] === ":") { tokens.shift(); triggerSpec.throttle = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA)); } else if (token === "queue" && tokens[0] === ":") { tokens.shift(); triggerSpec.queue = consumeUntil(tokens, WHITESPACE_OR_COMMA); - } else if ((token === "root" || token === "threshold") && tokens[0] === ":") { + } else if (token === "root" && tokens[0] === ":") { + tokens.shift(); + triggerSpec[token] = consumeCSSSelector(tokens); + } else if (token === "threshold" && tokens[0] === ":") { tokens.shift(); triggerSpec[token] = consumeUntil(tokens, WHITESPACE_OR_COMMA); } else { @@ -3913,32 +3925,39 @@ return (function () { } } - function initButtonTracking(elt) { - // Handle submit buttons/inputs that have the form attribute set - // see https://developer.mozilla.org/docs/Web/HTML/Element/button - var form = resolveTarget("#" + getRawAttribute(elt, "form")) || closest(elt, "form") - if (!form) { - return + // Handle submit buttons/inputs that have the form attribute set + // see https://developer.mozilla.org/docs/Web/HTML/Element/button + function maybeSetLastButtonClicked(evt) { + var elt = closest(evt.target, "button, input[type='submit']"); + var internalData = getRelatedFormData(evt) + if (internalData) { + internalData.lastButtonClicked = elt; } - - var maybeSetLastButtonClicked = function (evt) { - var elt = closest(evt.target, "button, input[type='submit']"); - if (elt !== null) { - var internalData = getInternalData(form); - internalData.lastButtonClicked = elt; - } - }; - + }; + function maybeUnsetLastButtonClicked(evt){ + var internalData = getRelatedFormData(evt) + if (internalData) { + internalData.lastButtonClicked = null; + } + } + function getRelatedFormData(evt) { + var elt = closest(evt.target, "button, input[type='submit']"); + if (!elt) { + return; + } + var form = resolveTarget('#' + getRawAttribute(elt, 'form')) || closest(elt, 'form'); + if (!form) { + return; + } + return getInternalData(form); + } + function initButtonTracking(elt) { // need to handle both click and focus in: // focusin - in case someone tabs in to a button and hits the space bar // click - on OSX buttons do not focus on click see https://bugs.webkit.org/show_bug.cgi?id=13724 - elt.addEventListener('click', maybeSetLastButtonClicked) elt.addEventListener('focusin', maybeSetLastButtonClicked) - elt.addEventListener('focusout', function(evt){ - var internalData = getInternalData(form); - internalData.lastButtonClicked = null; - }) + elt.addEventListener('focusout', maybeUnsetLastButtonClicked) } function countCurlies(line) { @@ -3957,7 +3976,9 @@ return (function () { function addHxOnEventHandler(elt, eventName, code) { var nodeData = getInternalData(elt); - nodeData.onHandlers = []; + if (!Array.isArray(nodeData.onHandlers)) { + nodeData.onHandlers = []; + } var func; var listener = function (e) { return maybeEval(elt, function() { @@ -4176,6 +4197,12 @@ return (function () { return; } + if (htmx.config.historyCacheSize <= 0) { + // make sure that an eventually already existing cache is purged + localStorage.removeItem("htmx-history-cache"); + return; + } + url = normalizePath(url); var historyCache = parseJSON(localStorage.getItem("htmx-history-cache")) || []; @@ -4441,7 +4468,7 @@ return (function () { if (shouldInclude(elt)) { var name = getRawAttribute(elt,"name"); var value = elt.value; - if (elt.multiple) { + if (elt.multiple && elt.tagName === "SELECT") { value = toArray(elt.querySelectorAll("option:checked")).map(function (e) { return e.value }); } // include file inputs @@ -4481,6 +4508,9 @@ return (function () { var formValues = {}; var errors = []; var internalData = getInternalData(elt); + if (internalData.lastButtonClicked && !bodyContains(internalData.lastButtonClicked)) { + internalData.lastButtonClicked = null + } // only validate when form is directly submitted and novalidate or formnovalidate are not set // or if the element has an explicit hx-validate="true" on it @@ -4648,7 +4678,7 @@ return (function () { "swapDelay" : htmx.config.defaultSwapDelay, "settleDelay" : htmx.config.defaultSettleDelay } - if (getInternalData(elt).boosted && !isAnchorLink(elt)) { + if (htmx.config.scrollIntoViewOnBoost && getInternalData(elt).boosted && !isAnchorLink(elt)) { swapSpec["show"] = "top" } if (swapInfo) { @@ -4888,6 +4918,7 @@ return (function () { values : context.values, targetOverride: resolveTarget(context.target), swapOverride: context.swap, + select: context.select, returnPromise: true }); } @@ -4942,6 +4973,7 @@ return (function () { elt = getDocument().body; } var responseHandler = etc.handler || handleAjaxResponse; + var select = etc.select || null; if (!bodyContains(elt)) { // do not issue requests for elements removed from the DOM @@ -4966,16 +4998,20 @@ return (function () { var buttonVerb = getRawAttribute(submitter, "formmethod") if (buttonVerb != null) { - verb = buttonVerb; + // ignore buttons with formmethod="dialog" + if (buttonVerb.toLowerCase() !== "dialog") { + verb = buttonVerb; + } } } + var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm"); // allow event-based confirmation w/ a callback - if (!confirmed) { - var issueRequest = function() { - return issueAjaxRequest(verb, path, elt, event, etc, true); + if (confirmed === undefined) { + var issueRequest = function(skipConfirmation) { + return issueAjaxRequest(verb, path, elt, event, etc, !!skipConfirmation); } - var confirmDetails = {target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest}; + var confirmDetails = {target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest, question: confirmQuestion}; if (triggerEvent(elt, 'htmx:confirm', confirmDetails) === false) { maybeCall(resolve); return promise; @@ -5076,8 +5112,7 @@ return (function () { } } - var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm"); - if (confirmQuestion) { + if (confirmQuestion && !confirmed) { if(!confirm(confirmQuestion)) { maybeCall(resolve); endRequestLock() @@ -5087,6 +5122,11 @@ return (function () { var headers = getHeaders(elt, target, promptResponse); + + if (verb !== 'get' && !usesFormData(elt)) { + headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + if (etc.headers) { headers = mergeObjects(headers, etc.headers); } @@ -5100,10 +5140,6 @@ return (function () { var allParameters = mergeObjects(rawParameters, expressionVars); var filteredParameters = filterValues(allParameters, elt); - if (verb !== 'get' && !usesFormData(elt)) { - headers['Content-Type'] = 'application/x-www-form-urlencoded'; - } - if (htmx.config.getCacheBusterParam && verb === 'get') { filteredParameters['org.htmx.cache-buster'] = getRawAttribute(target, "id") || "true"; } @@ -5201,7 +5237,7 @@ return (function () { } var responseInfo = { - xhr: xhr, target: target, requestConfig: requestConfig, etc: etc, boosted: eltIsBoosted, + xhr: xhr, target: target, requestConfig: requestConfig, etc: etc, boosted: eltIsBoosted, select: select, pathInfo: { requestPath: path, finalRequestPath: finalPath, @@ -5372,6 +5408,7 @@ return (function () { var target = responseInfo.target; var etc = responseInfo.etc; var requestConfig = responseInfo.requestConfig; + var select = responseInfo.select; if (!triggerEvent(elt, 'htmx:beforeOnLoad', responseInfo)) return; @@ -5481,10 +5518,26 @@ return (function () { } var selectOverride; + if (select) { + selectOverride = select; + } + if (hasHeader(xhr, /HX-Reselect:/i)) { selectOverride = xhr.getResponseHeader("HX-Reselect"); } + // if we need to save history, do so, before swapping so that relative resources have the correct base URL + if (historyUpdate.type) { + triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo)); + if (historyUpdate.type === "push") { + pushUrlIntoHistory(historyUpdate.path); + triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path: historyUpdate.path}); + } else { + replaceUrlInHistory(historyUpdate.path); + triggerEvent(getDocument().body, 'htmx:replacedInHistory', {path: historyUpdate.path}); + } + } + var settleInfo = makeSettleInfo(target); selectAndSwap(swapSpec.swapStyle, target, elt, serverResponse, settleInfo, selectOverride); @@ -5534,18 +5587,8 @@ return (function () { triggerEvent(elt, 'htmx:afterSettle', responseInfo); }); - // if we need to save history, do so - if (historyUpdate.type) { - if (historyUpdate.type === "push") { - pushUrlIntoHistory(historyUpdate.path); - triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path: historyUpdate.path}); - } else { - replaceUrlInHistory(historyUpdate.path); - triggerEvent(getDocument().body, 'htmx:replacedInHistory', {path: historyUpdate.path}); - } - } if (responseInfo.pathInfo.anchor) { - var anchorTarget = find("#" + responseInfo.pathInfo.anchor); + var anchorTarget = getDocument().getElementById(responseInfo.pathInfo.anchor); if(anchorTarget) { anchorTarget.scrollIntoView({block:'start', behavior: "auto"}); } @@ -5702,25 +5745,34 @@ return (function () { //==================================================================== // Initialization //==================================================================== - var isReady = false - getDocument().addEventListener('DOMContentLoaded', function() { - isReady = true - }) - /** - * Execute a function now if DOMContentLoaded has fired, otherwise listen for it. - * - * This function uses isReady because there is no realiable way to ask the browswer whether - * the DOMContentLoaded event has already been fired; there's a gap between DOMContentLoaded - * firing and readystate=complete. + * We want to initialize the page elements after DOMContentLoaded + * fires, but there isn't always a good way to tell whether + * it has already fired when we get here or not. */ - function ready(fn) { - // Checking readyState here is a failsafe in case the htmx script tag entered the DOM by - // some means other than the initial page load. - if (isReady || getDocument().readyState === 'complete') { - fn(); - } else { - getDocument().addEventListener('DOMContentLoaded', fn); + function ready(functionToCall) { + // call the function exactly once no matter how many times this is called + var callReadyFunction = function() { + if (!functionToCall) return; + functionToCall(); + functionToCall = null; + }; + + if (getDocument().readyState === "complete") { + // DOMContentLoaded definitely fired, we can initialize the page + callReadyFunction(); + } + else { + /* DOMContentLoaded *maybe* already fired, wait for + * the next DOMContentLoaded or readystatechange event + */ + getDocument().addEventListener("DOMContentLoaded", function() { + callReadyFunction(); + }); + getDocument().addEventListener("readystatechange", function() { + if (getDocument().readyState !== "complete") return; + callReadyFunction(); + }); } } @@ -5728,9 +5780,9 @@ return (function () { if (htmx.config.includeIndicatorStyles !== false) { getDocument().head.insertAdjacentHTML("beforeend", "<style>\ - ." + htmx.config.indicatorClass + "{opacity:0;transition: opacity 200ms ease-in;}\ - ." + htmx.config.requestClass + " ." + htmx.config.indicatorClass + "{opacity:1}\ - ." + htmx.config.requestClass + "." + htmx.config.indicatorClass + "{opacity:1}\ + ." + htmx.config.indicatorClass + "{opacity:0}\ + ." + htmx.config.requestClass + " ." + htmx.config.indicatorClass + "{opacity:1; transition: opacity 200ms ease-in;}\ + ." + htmx.config.requestClass + "." + htmx.config.indicatorClass + "{opacity:1; transition: opacity 200ms ease-in;}\ </style>"); } } @@ -5946,5 +5998,5 @@ htmx.defineExtension("preload", { !function(e){if(!e.hasInitialised){var t={escapeRegExp:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},hasClass:function(e,t){var i=" ";return 1===e.nodeType&&(i+e.className+i).replace(/[\n\t]/g,i).indexOf(i+t+i)>=0},addClass:function(e,t){e.className+=" "+t},removeClass:function(e,t){var i=new RegExp("\\b"+this.escapeRegExp(t)+"\\b");e.className=e.className.replace(i,"")},interpolateString:function(e,t){var i=/{{([a-z][a-z0-9\-_]*)}}/gi;return e.replace(i,function(e){return t(arguments[1])||""})},getCookie:function(e){var t="; "+document.cookie,i=t.split("; "+e+"=");return i.length<2?void 0:i.pop().split(";").shift()},setCookie:function(e,t,i,n,o,s){var r=new Date;r.setDate(r.getDate()+(i||365));var a=[e+"="+t,"expires="+r.toUTCString(),"path="+(o||"/")];n&&a.push("domain="+n),s&&a.push("secure"),document.cookie=a.join(";")},deepExtend:function(e,t){for(var i in t)t.hasOwnProperty(i)&&(i in e&&this.isPlainObject(e[i])&&this.isPlainObject(t[i])?this.deepExtend(e[i],t[i]):e[i]=t[i]);return e},throttle:function(e,t){var i=!1;return function(){i||(e.apply(this,arguments),i=!0,setTimeout(function(){i=!1},t))}},hash:function(e){var t,i,n,o=0;if(0===e.length)return o;for(t=0,n=e.length;t<n;++t)i=e.charCodeAt(t),o=(o<<5)-o+i,o|=0;return o},normaliseHex:function(e){return"#"==e[0]&&(e=e.substr(1)),3==e.length&&(e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]),e},getContrast:function(e){e=this.normaliseHex(e);var t=parseInt(e.substr(0,2),16),i=parseInt(e.substr(2,2),16),n=parseInt(e.substr(4,2),16),o=(299*t+587*i+114*n)/1e3;return o>=128?"#000":"#fff"},getLuminance:function(e){var t=parseInt(this.normaliseHex(e),16),i=38,n=(t>>16)+i,o=(t>>8&255)+i,s=(255&t)+i,r=(16777216+65536*(n<255?n<1?0:n:255)+256*(o<255?o<1?0:o:255)+(s<255?s<1?0:s:255)).toString(16).slice(1);return"#"+r},isMobile:function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},isPlainObject:function(e){return"object"==typeof e&&null!==e&&e.constructor==Object},traverseDOMPath:function(e,i){return e&&e.parentNode?t.hasClass(e,i)?e:this.traverseDOMPath(e.parentNode,i):null}};e.status={deny:"deny",allow:"allow",dismiss:"dismiss"},e.transitionEnd=function(){var e=document.createElement("div"),t={t:"transitionend",OT:"oTransitionEnd",msT:"MSTransitionEnd",MozT:"transitionend",WebkitT:"webkitTransitionEnd"};for(var i in t)if(t.hasOwnProperty(i)&&"undefined"!=typeof e.style[i+"ransition"])return t[i];return""}(),e.hasTransition=!!e.transitionEnd;var i=Object.keys(e.status).map(t.escapeRegExp);e.customStyles={},e.Popup=function(){function n(){this.initialise.apply(this,arguments)}function o(e){this.openingTimeout=null,t.removeClass(e,"cc-invisible")}function s(t){t.style.display="none",t.removeEventListener(e.transitionEnd,this.afterTransition),this.afterTransition=null}function r(){var t=this.options.onInitialise.bind(this);if(!window.navigator.cookieEnabled)return t(e.status.deny),!0;if(window.CookiesOK||window.navigator.CookiesOK)return t(e.status.allow),!0;var i=Object.keys(e.status),n=this.getStatus(),o=i.indexOf(n)>=0;return o&&t(n),o}function a(){var e=this.options.position.split("-"),t=[];return e.forEach(function(e){t.push("cc-"+e)}),t}function c(){var e=this.options,i="top"==e.position||"bottom"==e.position?"banner":"floating";t.isMobile()&&(i="floating");var n=["cc-"+i,"cc-type-"+e.type,"cc-theme-"+e.theme];e["static"]&&n.push("cc-static"),n.push.apply(n,a.call(this));p.call(this,this.options.palette);return this.customStyleSelector&&n.push(this.customStyleSelector),n}function l(){var e={},i=this.options;i.showLink||(i.elements.link="",i.elements.messagelink=i.elements.message),Object.keys(i.elements).forEach(function(n){e[n]=t.interpolateString(i.elements[n],function(e){var t=i.content[e];return e&&"string"==typeof t&&t.length?t:""})});var n=i.compliance[i.type];n||(n=i.compliance.info),e.compliance=t.interpolateString(n,function(t){return e[t]});var o=i.layouts[i.layout];return o||(o=i.layouts.basic),t.interpolateString(o,function(t){return e[t]})}function u(i){var n=this.options,o=document.createElement("div"),s=n.container&&1===n.container.nodeType?n.container:document.body;o.innerHTML=i;var r=o.children[0];return r.style.display="none",t.hasClass(r,"cc-window")&&e.hasTransition&&t.addClass(r,"cc-invisible"),this.onButtonClick=h.bind(this),r.addEventListener("click",this.onButtonClick),n.autoAttach&&(s.firstChild?s.insertBefore(r,s.firstChild):s.appendChild(r)),r}function h(n){var o=t.traverseDOMPath(n.target,"cc-btn")||n.target;if(t.hasClass(o,"cc-btn")){var s=o.className.match(new RegExp("\\bcc-("+i.join("|")+")\\b")),r=s&&s[1]||!1;r&&(this.setStatus(r),this.close(!0))}t.hasClass(o,"cc-close")&&(this.setStatus(e.status.dismiss),this.close(!0)),t.hasClass(o,"cc-revoke")&&this.revokeChoice()}function p(e){var i=t.hash(JSON.stringify(e)),n="cc-color-override-"+i,o=t.isPlainObject(e);return this.customStyleSelector=o?n:null,o&&d(i,e,"."+n),o}function d(i,n,o){if(e.customStyles[i])return void++e.customStyles[i].references;var s={},r=n.popup,a=n.button,c=n.highlight;r&&(r.text=r.text?r.text:t.getContrast(r.background),r.link=r.link?r.link:r.text,s[o+".cc-window"]=["color: "+r.text,"background-color: "+r.background],s[o+".cc-revoke"]=["color: "+r.text,"background-color: "+r.background],s[o+" .cc-link,"+o+" .cc-link:active,"+o+" .cc-link:visited"]=["color: "+r.link],a&&(a.text=a.text?a.text:t.getContrast(a.background),a.border=a.border?a.border:"transparent",s[o+" .cc-btn"]=["color: "+a.text,"border-color: "+a.border,"background-color: "+a.background],a.padding&&s[o+" .cc-btn"].push("padding: "+a.padding),"transparent"!=a.background&&(s[o+" .cc-btn:hover, "+o+" .cc-btn:focus"]=["background-color: "+(a.hover||v(a.background))]),c?(c.text=c.text?c.text:t.getContrast(c.background),c.border=c.border?c.border:"transparent",s[o+" .cc-highlight .cc-btn:first-child"]=["color: "+c.text,"border-color: "+c.border,"background-color: "+c.background]):s[o+" .cc-highlight .cc-btn:first-child"]=["color: "+r.text]));var l=document.createElement("style");document.head.appendChild(l),e.customStyles[i]={references:1,element:l.sheet};var u=-1;for(var h in s)s.hasOwnProperty(h)&&l.sheet.insertRule(h+"{"+s[h].join(";")+"}",++u)}function v(e){return e=t.normaliseHex(e),"000000"==e?"#222":t.getLuminance(e)}function f(i){if(t.isPlainObject(i)){var n=t.hash(JSON.stringify(i)),o=e.customStyles[n];if(o&&!--o.references){var s=o.element.ownerNode;s&&s.parentNode&&s.parentNode.removeChild(s),e.customStyles[n]=null}}}function m(e,t){for(var i=0,n=e.length;i<n;++i){var o=e[i];if(o instanceof RegExp&&o.test(t)||"string"==typeof o&&o.length&&o===t)return!0}return!1}function b(){var i=this.setStatus.bind(this),n=this.close.bind(this),o=this.options.dismissOnTimeout;"number"==typeof o&&o>=0&&(this.dismissTimeout=window.setTimeout(function(){i(e.status.dismiss),n(!0)},Math.floor(o)));var s=this.options.dismissOnScroll;if("number"==typeof s&&s>=0){var r=function(t){window.pageYOffset>Math.floor(s)&&(i(e.status.dismiss),n(!0),window.removeEventListener("scroll",r),this.onWindowScroll=null)};this.options.enabled&&(this.onWindowScroll=r,window.addEventListener("scroll",r))}var a=this.options.dismissOnWindowClick,c=this.options.ignoreClicksFrom;if(a){var l=function(o){for(var s=!1,r=o.path.length,a=c.length,u=0;u<r;u++)if(!s)for(var h=0;h<a;h++)s||(s=t.hasClass(o.path[u],c[h]));s||(i(e.status.dismiss),n(!0),window.removeEventListener("click",l),this.onWindowClick=null)}.bind(this);this.options.enabled&&(this.onWindowClick=l,window.addEventListener("click",l))}}function g(){if("info"!=this.options.type&&(this.options.revokable=!0),t.isMobile()&&(this.options.animateRevokable=!1),this.options.revokable){var e=a.call(this);this.options.animateRevokable&&e.push("cc-animate"),this.customStyleSelector&&e.push(this.customStyleSelector);var i=this.options.revokeBtn.replace("{{classes}}",e.join(" ")).replace("{{policy}}",this.options.content.policy);this.revokeBtn=u.call(this,i);var n=this.revokeBtn;if(this.options.animateRevokable){var o=t.throttle(function(e){var i=!1,o=20,s=window.innerHeight-20;t.hasClass(n,"cc-top")&&e.clientY<o&&(i=!0),t.hasClass(n,"cc-bottom")&&e.clientY>s&&(i=!0),i?t.hasClass(n,"cc-active")||t.addClass(n,"cc-active"):t.hasClass(n,"cc-active")&&t.removeClass(n,"cc-active")},200);this.onMouseMove=o,window.addEventListener("mousemove",o)}}}var y={enabled:!0,container:null,cookie:{name:"cookieconsent_status",path:"/",domain:"",expiryDays:365,secure:!1},onPopupOpen:function(){},onPopupClose:function(){},onInitialise:function(e){},onStatusChange:function(e,t){},onRevokeChoice:function(){},onNoCookieLaw:function(e,t){},content:{header:"Cookies used on the website!",message:"This website uses cookies to ensure you get the best experience on our website.",dismiss:"Got it!",allow:"Allow cookies",deny:"Decline",link:"Learn more",href:"https://cookiesandyou.com",close:"❌",target:"_blank",policy:"Cookie Policy"},elements:{header:'<span class="cc-header">{{header}}</span> ',message:'<span id="cookieconsent:desc" class="cc-message">{{message}}</span>',messagelink:'<span id="cookieconsent:desc" class="cc-message">{{message}} <a aria-label="learn more about cookies" role=button tabindex="0" class="cc-link" href="{{href}}" rel="noopener noreferrer nofollow" target="{{target}}">{{link}}</a></span>',dismiss:'<a aria-label="dismiss cookie message" role=button tabindex="0" class="cc-btn cc-dismiss">{{dismiss}}</a>',allow:'<a aria-label="allow cookies" role=button tabindex="0" class="cc-btn cc-allow">{{allow}}</a>',deny:'<a aria-label="deny cookies" role=button tabindex="0" class="cc-btn cc-deny">{{deny}}</a>',link:'<a aria-label="learn more about cookies" role=button tabindex="0" class="cc-link" href="{{href}}" rel="noopener noreferrer nofollow" target="{{target}}">{{link}}</a>',close:'<span aria-label="dismiss cookie message" role=button tabindex="0" class="cc-close">{{close}}</span>'},window:'<div role="dialog" aria-live="polite" aria-label="cookieconsent" aria-describedby="cookieconsent:desc" class="cc-window {{classes}}"><!--googleoff: all-->{{children}}<!--googleon: all--></div>',revokeBtn:'<div class="cc-revoke {{classes}}">{{policy}}</div>',compliance:{info:'<div class="cc-compliance">{{dismiss}}</div>',"opt-in":'<div class="cc-compliance cc-highlight">{{deny}}{{allow}}</div>',"opt-out":'<div class="cc-compliance cc-highlight">{{deny}}{{allow}}</div>'},type:"info",layouts:{basic:"{{messagelink}}{{compliance}}","basic-close":"{{messagelink}}{{compliance}}{{close}}","basic-header":"{{header}}{{message}}{{link}}{{compliance}}"},layout:"basic",position:"bottom",theme:"block","static":!1,palette:null,revokable:!1,animateRevokable:!0,showLink:!0,dismissOnScroll:!1,dismissOnTimeout:!1,dismissOnWindowClick:!1,ignoreClicksFrom:["cc-revoke","cc-btn"],autoOpen:!0,autoAttach:!0,whitelistPage:[],blacklistPage:[],overrideHTML:null};return n.prototype.initialise=function(e){this.options&&this.destroy(),t.deepExtend(this.options={},y),t.isPlainObject(e)&&t.deepExtend(this.options,e),r.call(this)&&(this.options.enabled=!1),m(this.options.blacklistPage,location.pathname)&&(this.options.enabled=!1),m(this.options.whitelistPage,location.pathname)&&(this.options.enabled=!0);var i=this.options.window.replace("{{classes}}",c.call(this).join(" ")).replace("{{children}}",l.call(this)),n=this.options.overrideHTML;if("string"==typeof n&&n.length&&(i=n),this.options["static"]){var o=u.call(this,'<div class="cc-grower">'+i+"</div>");o.style.display="",this.element=o.firstChild,this.element.style.display="none",t.addClass(this.element,"cc-invisible")}else this.element=u.call(this,i);b.call(this),g.call(this),this.options.autoOpen&&this.autoOpen()},n.prototype.destroy=function(){this.onButtonClick&&this.element&&(this.element.removeEventListener("click",this.onButtonClick),this.onButtonClick=null),this.dismissTimeout&&(clearTimeout(this.dismissTimeout),this.dismissTimeout=null),this.onWindowScroll&&(window.removeEventListener("scroll",this.onWindowScroll),this.onWindowScroll=null),this.onWindowClick&&(window.removeEventListener("click",this.onWindowClick),this.onWindowClick=null),this.onMouseMove&&(window.removeEventListener("mousemove",this.onMouseMove),this.onMouseMove=null),this.element&&this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.element=null,this.revokeBtn&&this.revokeBtn.parentNode&&this.revokeBtn.parentNode.removeChild(this.revokeBtn),this.revokeBtn=null,f(this.options.palette),this.options=null},n.prototype.open=function(t){if(this.element)return this.isOpen()||(e.hasTransition?this.fadeIn():this.element.style.display="",this.options.revokable&&this.toggleRevokeButton(),this.options.onPopupOpen.call(this)),this},n.prototype.close=function(t){if(this.element)return this.isOpen()&&(e.hasTransition?this.fadeOut():this.element.style.display="none",t&&this.options.revokable&&this.toggleRevokeButton(!0),this.options.onPopupClose.call(this)),this},n.prototype.fadeIn=function(){var i=this.element;if(e.hasTransition&&i&&(this.afterTransition&&s.call(this,i),t.hasClass(i,"cc-invisible"))){if(i.style.display="",this.options["static"]){var n=this.element.clientHeight;this.element.parentNode.style.maxHeight=n+"px"}var r=20;this.openingTimeout=setTimeout(o.bind(this,i),r)}},n.prototype.fadeOut=function(){var i=this.element;e.hasTransition&&i&&(this.openingTimeout&&(clearTimeout(this.openingTimeout),o.bind(this,i)),t.hasClass(i,"cc-invisible")||(this.options["static"]&&(this.element.parentNode.style.maxHeight=""),this.afterTransition=s.bind(this,i),i.addEventListener(e.transitionEnd,this.afterTransition),t.addClass(i,"cc-invisible")))},n.prototype.isOpen=function(){return this.element&&""==this.element.style.display&&(!e.hasTransition||!t.hasClass(this.element,"cc-invisible"))},n.prototype.toggleRevokeButton=function(e){this.revokeBtn&&(this.revokeBtn.style.display=e?"":"none")},n.prototype.revokeChoice=function(e){this.options.enabled=!0,this.clearStatus(),this.options.onRevokeChoice.call(this),e||this.autoOpen()},n.prototype.hasAnswered=function(t){return Object.keys(e.status).indexOf(this.getStatus())>=0},n.prototype.hasConsented=function(t){var i=this.getStatus();return i==e.status.allow||i==e.status.dismiss},n.prototype.autoOpen=function(e){!this.hasAnswered()&&this.options.enabled?this.open():this.hasAnswered()&&this.options.revokable&&this.toggleRevokeButton(!0)},n.prototype.setStatus=function(i){var n=this.options.cookie,o=t.getCookie(n.name),s=Object.keys(e.status).indexOf(o)>=0;Object.keys(e.status).indexOf(i)>=0?(t.setCookie(n.name,i,n.expiryDays,n.domain,n.path,n.secure),this.options.onStatusChange.call(this,i,s)):this.clearStatus()},n.prototype.getStatus=function(){return t.getCookie(this.options.cookie.name)},n.prototype.clearStatus=function(){var e=this.options.cookie;t.setCookie(e.name,"",-1,e.domain,e.path)},n}(),e.Location=function(){function e(e){t.deepExtend(this.options={},s),t.isPlainObject(e)&&t.deepExtend(this.options,e),this.currentServiceIndex=-1}function i(e,t,i){var n,o=document.createElement("script");o.type="text/"+(e.type||"javascript"),o.src=e.src||e,o.async=!1,o.onreadystatechange=o.onload=function(){var e=o.readyState;clearTimeout(n),t.done||e&&!/loaded|complete/.test(e)||(t.done=!0,t(),o.onreadystatechange=o.onload=null)},document.body.appendChild(o),n=setTimeout(function(){t.done=!0,t(),o.onreadystatechange=o.onload=null},i)}function n(e,t,i,n,o){var s=new(window.XMLHttpRequest||window.ActiveXObject)("MSXML2.XMLHTTP.3.0");if(s.open(n?"POST":"GET",e,1),s.setRequestHeader("Content-type","application/x-www-form-urlencoded"),Array.isArray(o))for(var r=0,a=o.length;r<a;++r){var c=o[r].split(":",2);s.setRequestHeader(c[0].replace(/^\s+|\s+$/g,""),c[1].replace(/^\s+|\s+$/g,""))}"function"==typeof t&&(s.onreadystatechange=function(){s.readyState>3&&t(s)}),s.send(n)}function o(e){return new Error("Error ["+(e.code||"UNKNOWN")+"]: "+e.error)}var s={timeout:5e3,services:["ipinfo"],serviceDefinitions:{ipinfo:function(){return{url:"//ipinfo.io",headers:["Accept: application/json"],callback:function(e,t){try{var i=JSON.parse(t);return i.error?o(i):{code:i.country}}catch(n){return o({error:"Invalid response ("+n+")"})}}}},ipinfodb:function(e){return{url:"//api.ipinfodb.com/v3/ip-country/?key={api_key}&format=json&callback={callback}",isScript:!0,callback:function(e,t){try{var i=JSON.parse(t);return"ERROR"==i.statusCode?o({error:i.statusMessage}):{code:i.countryCode}}catch(n){return o({error:"Invalid response ("+n+")"})}}}},maxmind:function(){return{url:"//js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js",isScript:!0,callback:function(e){return window.geoip2?void geoip2.country(function(t){try{e({code:t.country.iso_code})}catch(i){e(o(i))}},function(t){e(o(t))}):void e(new Error("Unexpected response format. The downloaded script should have exported `geoip2` to the global scope"))}}}}};return e.prototype.getNextService=function(){var e;do e=this.getServiceByIdx(++this.currentServiceIndex);while(this.currentServiceIndex<this.options.services.length&&!e);return e},e.prototype.getServiceByIdx=function(e){var i=this.options.services[e];if("function"==typeof i){var n=i();return n.name&&t.deepExtend(n,this.options.serviceDefinitions[n.name](n)),n}return"string"==typeof i?this.options.serviceDefinitions[i]():t.isPlainObject(i)?this.options.serviceDefinitions[i.name](i):null},e.prototype.locate=function(e,t){var i=this.getNextService();return i?(this.callbackComplete=e,this.callbackError=t,void this.runService(i,this.runNextServiceOnError.bind(this))):void t(new Error("No services to run"))},e.prototype.setupUrl=function(e){var t=this.getCurrentServiceOpts();return e.url.replace(/\{(.*?)\}/g,function(i,n){if("callback"===n){var o="callback"+Date.now();return window[o]=function(t){e.__JSONP_DATA=JSON.stringify(t)},o}if(n in t.interpolateUrl)return t.interpolateUrl[n]})},e.prototype.runService=function(e,t){var o=this;if(e&&e.url&&e.callback){var s=e.isScript?i:n,r=this.setupUrl(e);s(r,function(i){var n=i?i.responseText:"";e.__JSONP_DATA&&(n=e.__JSONP_DATA,delete e.__JSONP_DATA),o.runServiceCallback.call(o,t,e,n)},this.options.timeout,e.data,e.headers)}},e.prototype.runServiceCallback=function(e,t,i){var n=this,o=function(t){s||n.onServiceResult.call(n,e,t)},s=t.callback(o,i);s&&this.onServiceResult.call(this,e,s)},e.prototype.onServiceResult=function(e,t){t instanceof Error||t&&t.error?e.call(this,t,null):e.call(this,null,t)},e.prototype.runNextServiceOnError=function(e,t){if(e){this.logError(e);var i=this.getNextService();i?this.runService(i,this.runNextServiceOnError.bind(this)):this.completeService.call(this,this.callbackError,new Error("All services failed"))}else this.completeService.call(this,this.callbackComplete,t)},e.prototype.getCurrentServiceOpts=function(){var e=this.options.services[this.currentServiceIndex];return"string"==typeof e?{name:e}:"function"==typeof e?e():t.isPlainObject(e)?e:{}},e.prototype.completeService=function(e,t){this.currentServiceIndex=-1,e&&e(t)},e.prototype.logError=function(e){var t=this.currentServiceIndex,i=this.getServiceByIdx(t);console.warn("The service["+t+"] ("+i.url+") responded with the following error",e)},e}(),e.Law=function(){function e(e){this.initialise.apply(this,arguments)}var i={regionalLaw:!0,hasLaw:["AT","BE","BG","HR","CZ","CY","DK","EE","FI","FR","DE","EL","HU","IE","IT","LV","LT","LU","MT","NL","PL","PT","SK","ES","SE","GB","UK","GR","EU"],revokable:["HR","CY","DK","EE","FR","DE","LV","LT","NL","PT","ES"],explicitAction:["HR","IT","ES"]};return e.prototype.initialise=function(e){t.deepExtend(this.options={},i),t.isPlainObject(e)&&t.deepExtend(this.options,e)},e.prototype.get=function(e){var t=this.options;return{hasLaw:t.hasLaw.indexOf(e)>=0,revokable:t.revokable.indexOf(e)>=0,explicitAction:t.explicitAction.indexOf(e)>=0}},e.prototype.applyLaw=function(e,t){var i=this.get(t);return i.hasLaw||(e.enabled=!1,"function"==typeof e.onNoCookieLaw&&e.onNoCookieLaw(t,i)),this.options.regionalLaw&&(i.revokable&&(e.revokable=!0),i.explicitAction&&(e.dismissOnScroll=!1,e.dismissOnTimeout=!1)),e},e}(),e.initialise=function(i,n,o){var s=new e.Law(i.law);n||(n=function(){}),o||(o=function(){});var r=Object.keys(e.status),a=t.getCookie("cookieconsent_status"),c=r.indexOf(a)>=0;return c?void n(new e.Popup(i)):void e.getCountryCode(i,function(t){delete i.law,delete i.location,t.code&&(i=s.applyLaw(i,t.code)),n(new e.Popup(i))},function(t){delete i.law,delete i.location,o(t,new e.Popup(i))})},e.getCountryCode=function(t,i,n){if(t.law&&t.law.countryCode)return void i({code:t.law.countryCode});if(t.location){var o=new e.Location(t.location);return void o.locate(function(e){i(e||{})},n)}i({})},e.utils=t,e.hasInitialised=!0,window.cookieconsent=e}}(window.cookieconsent||{}); function jsBundleVersion() { - return "6b3b1791facc58d99b1e9c143e69bd45"; + return "2fb8693374ebdea0ffcbb3b8c1d39910"; } diff --git a/groups.io/tinymce-4.7.13/tinymce.min.js b/groups.io/tinymce-4.7.13/tinymce.min.js deleted file mode 100644 index 00895af8..00000000 --- a/groups.io/tinymce-4.7.13/tinymce.min.js +++ /dev/null @@ -1,2 +0,0 @@ -// 4.7.13 (2018-05-16) -!function(){"use strict";var e,t,n,r,o,i,a,u,s,c,l,f,d,m,p,g,h,v=function(e){return function(){return e}},y=v(!1),b=v(!0),V={noop:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t]},noarg:function(n){return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return n()}},compose:function(n,r){return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return n(r.apply(null,arguments))}},constant:v,identity:function(e){return e},tripleEquals:function(e,t){return e===t},curry:function(i){for(var e=[],t=1;t<arguments.length;t++)e[t-1]=arguments[t];for(var a=new Array(arguments.length-1),n=1;n<arguments.length;n++)a[n-1]=arguments[n];return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];var o=a.concat(n);return i.apply(null,o)}},not:function(n){return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return!n.apply(null,arguments)}},die:function(e){return function(){throw new Error(e)}},apply:function(e){return e()},call:function(e){e()},never:y,always:b},C=V.never,x=V.always,w=function(){return N},N=(r={fold:function(e,t){return e()},is:C,isSome:C,isNone:x,getOr:n=function(e){return e},getOrThunk:t=function(e){return e()},getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},or:n,orThunk:t,map:w,ap:w,each:function(){},bind:w,flatten:w,exists:C,forall:x,filter:w,equals:e=function(e){return e.isNone()},equals_:e,toArray:function(){return[]},toString:V.constant("none()")},Object.freeze&&Object.freeze(r),r),E=function(n){var e=function(){return n},t=function(){return o},r=function(e){return e(n)},o={fold:function(e,t){return t(n)},is:function(e){return n===e},isSome:x,isNone:C,getOr:e,getOrThunk:e,getOrDie:e,or:t,orThunk:t,map:function(e){return E(e(n))},ap:function(e){return e.fold(w,function(e){return E(e(n))})},each:function(e){e(n)},bind:r,flatten:e,exists:r,forall:r,filter:function(e){return e(n)?o:N},equals:function(e){return e.is(n)},equals_:function(e,t){return e.fold(C,function(e){return t(n,e)})},toArray:function(){return[n]},toString:function(){return"some("+n+")"}};return o},A={some:E,none:w,from:function(e){return null===e||e===undefined?N:E(e)}},S=function(t){return function(e){return function(e){if(null===e)return"null";var t=typeof e;return"object"===t&&Array.prototype.isPrototypeOf(e)?"array":"object"===t&&String.prototype.isPrototypeOf(e)?"string":t}(e)===t}},k={isString:S("string"),isObject:S("object"),isArray:S("array"),isNull:S("null"),isBoolean:S("boolean"),isUndefined:S("undefined"),isFunction:S("function"),isNumber:S("number")},T=(o=Array.prototype.indexOf)===undefined?function(e,t){return L(e,t)}:function(e,t){return o.call(e,t)},R=function(e,t){return-1<T(e,t)},_=function(e,t){for(var n=e.length,r=new Array(n),o=0;o<n;o++){var i=e[o];r[o]=t(i,o,e)}return r},B=function(e,t){for(var n=0,r=e.length;n<r;n++)t(e[n],n,e)},D=function(e,t){for(var n=e.length-1;0<=n;n--)t(e[n],n,e)},O=function(e,t){for(var n=[],r=0,o=e.length;r<o;r++){var i=e[r];t(i,r,e)&&n.push(i)}return n},P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(t(e[n],n,e))return A.some(n);return A.none()},L=function(e,t){for(var n=0,r=e.length;n<r;++n)if(e[n]===t)return n;return-1},I=Array.prototype.push,M=function(e){for(var t=[],n=0,r=e.length;n<r;++n){if(!Array.prototype.isPrototypeOf(e[n]))throw new Error("Arr.flatten item "+n+" was not an array, input: "+e);I.apply(t,e[n])}return t},F=function(e,t){for(var n=0,r=e.length;n<r;++n)if(!0!==t(e[n],n,e))return!1;return!0},z=Array.prototype.slice,U=k.isFunction(Array.from)?Array.from:function(e){return z.call(e)},H={map:_,each:B,eachr:D,partition:function(e,t){for(var n=[],r=[],o=0,i=e.length;o<i;o++){var a=e[o];(t(a,o,e)?n:r).push(a)}return{pass:n,fail:r}},filter:O,groupBy:function(e,t){if(0===e.length)return[];for(var n=t(e[0]),r=[],o=[],i=0,a=e.length;i<a;i++){var u=e[i],s=t(u);s!==n&&(r.push(o),o=[]),n=s,o.push(u)}return 0!==o.length&&r.push(o),r},indexOf:function(e,t){var n=T(e,t);return-1===n?A.none():A.some(n)},foldr:function(e,t,n){return D(e,function(e){n=t(n,e)}),n},foldl:function(e,t,n){return B(e,function(e){n=t(n,e)}),n},find:function(e,t){for(var n=0,r=e.length;n<r;n++){var o=e[n];if(t(o,n,e))return A.some(o)}return A.none()},findIndex:P,flatten:M,bind:function(e,t){var n=_(e,t);return M(n)},forall:F,exists:function(e,t){return P(e,t).isSome()},contains:R,equal:function(e,n){return e.length===n.length&&F(e,function(e,t){return e===n[t]})},reverse:function(e){var t=z.call(e,0);return t.reverse(),t},chunk:function(e,t){for(var n=[],r=0;r<e.length;r+=t){var o=e.slice(r,r+t);n.push(o)}return n},difference:function(e,t){return O(e,function(e){return!R(t,e)})},mapToObject:function(e,t){for(var n={},r=0,o=e.length;r<o;r++){var i=e[r];n[String(i)]=t(i,r)}return n},pure:function(e){return[e]},sort:function(e,t){var n=z.call(e,0);return n.sort(t),n},range:function(e,t){for(var n=[],r=0;r<e;r++)n.push(t(r));return n},head:function(e){return 0===e.length?A.none():A.some(e[0])},last:function(e){return 0===e.length?A.none():A.some(e[e.length-1])},from:U},q="undefined"!=typeof window?window:Function("return this;")(),j=function(e,t){for(var n=t!==undefined&&null!==t?t:q,r=0;r<e.length&&n!==undefined&&null!==n;++r)n=n[e[r]];return n},$=function(e,t){var n=e.split(".");return j(n,t)},W={getOrDie:function(e,t){var n=$(e,t);if(n===undefined||null===n)throw e+" not available on this browser";return n}},K=function(){return W.getOrDie("URL")},X={createObjectURL:function(e){return K().createObjectURL(e)},revokeObjectURL:function(e){K().revokeObjectURL(e)}},Y=navigator,G=Y.userAgent,J=function(e){return"matchMedia"in window&&matchMedia(e).matches};d=/Android/.test(G),a=(a=!(i=/WebKit/.test(G))&&/MSIE/gi.test(G)&&/Explorer/gi.test(Y.appName))&&/MSIE (\w+)\./.exec(G)[1],u=-1!==G.indexOf("Trident/")&&(-1!==G.indexOf("rv:")||-1!==Y.appName.indexOf("Netscape"))&&11,s=-1!==G.indexOf("Edge/")&&!a&&!u&&12,a=a||u||s,c=!i&&!u&&/Gecko/.test(G),l=-1!==G.indexOf("Mac"),f=/(iPad|iPhone)/.test(G),m="FormData"in window&&"FileReader"in window&&"URL"in window&&!!X.createObjectURL,p=J("only screen and (max-device-width: 480px)")&&(d||f),g=J("only screen and (min-width: 800px)")&&(d||f),h=-1!==G.indexOf("Windows Phone"),s&&(i=!1);var Q,Z,ee,te,ne,re,oe,ie,ae,ue,se,ce,le,fe,de,me,pe,ge,he,ve={opera:!1,webkit:i,ie:a,gecko:c,mac:l,iOS:f,android:d,contentEditable:!f||m||534<=parseInt(G.match(/AppleWebKit\/(\d*)/)[1],10),transparentSrc:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",caretAfter:8!==a,range:window.getSelection&&"Range"in window,documentMode:a&&!s?document.documentMode||7:10,fileApi:m,ceFalse:!1===a||8<a,cacheSuffix:null,container:null,overrideViewPort:null,experimentalShadowDom:!1,canHaveCSP:!1===a||11<a,desktop:!p&&!g,windowsPhone:h},ye=window.Promise?window.Promise:function(){function r(e,t){return function(){e.apply(t,arguments)}}var e=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)},i=function(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],l(e,r(o,this),r(u,this))},t=i.immediateFn||"function"==typeof setImmediate&&setImmediate||function(e){setTimeout(e,1)};function a(r){var o=this;null!==this._state?t(function(){var e=o._state?r.onFulfilled:r.onRejected;if(null!==e){var t;try{t=e(o._value)}catch(n){return void r.reject(n)}r.resolve(t)}else(o._state?r.resolve:r.reject)(o._value)}):this._deferreds.push(r)}function o(e){try{if(e===this)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var t=e.then;if("function"==typeof t)return void l(r(t,e),r(o,this),r(u,this))}this._state=!0,this._value=e,s.call(this)}catch(n){u.call(this,n)}}function u(e){this._state=!1,this._value=e,s.call(this)}function s(){for(var e=0,t=this._deferreds.length;e<t;e++)a.call(this,this._deferreds[e]);this._deferreds=null}function c(e,t,n,r){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.resolve=n,this.reject=r}function l(e,t,n){var r=!1;try{e(function(e){r||(r=!0,t(e))},function(e){r||(r=!0,n(e))})}catch(o){if(r)return;r=!0,n(o)}}return i.prototype["catch"]=function(e){return this.then(null,e)},i.prototype.then=function(n,r){var o=this;return new i(function(e,t){a.call(o,new c(n,r,e,t))})},i.all=function(){var s=Array.prototype.slice.call(1===arguments.length&&e(arguments[0])?arguments[0]:arguments);return new i(function(o,i){if(0===s.length)return o([]);var a=s.length;function u(t,e){try{if(e&&("object"==typeof e||"function"==typeof e)){var n=e.then;if("function"==typeof n)return void n.call(e,function(e){u(t,e)},i)}s[t]=e,0==--a&&o(s)}catch(r){i(r)}}for(var e=0;e<s.length;e++)u(e,s[e])})},i.resolve=function(t){return t&&"object"==typeof t&&t.constructor===i?t:new i(function(e){e(t)})},i.reject=function(n){return new i(function(e,t){t(n)})},i.race=function(o){return new i(function(e,t){for(var n=0,r=o.length;n<r;n++)o[n].then(e,t)})},i}(),be=function(e,t){return"number"!=typeof t&&(t=0),setTimeout(e,t)},Ce=function(e,t){return"number"!=typeof t&&(t=1),setInterval(e,t)},xe=function(t,n){var r,e;return(e=function(){var e=arguments;clearTimeout(r),r=be(function(){t.apply(this,e)},n)}).stop=function(){clearTimeout(r)},e},we={requestAnimationFrame:function(e,t){Q?Q.then(e):Q=new ye(function(e){t||(t=document.body),function(e,t){var n,r=window.requestAnimationFrame,o=["ms","moz","webkit"];for(n=0;n<o.length&&!r;n++)r=window[o[n]+"RequestAnimationFrame"];r||(r=function(e){window.setTimeout(e,0)}),r(e,t)}(e,t)}).then(e)},setTimeout:be,setInterval:Ce,setEditorTimeout:function(e,t,n){return be(function(){e.removed||t()},n)},setEditorInterval:function(e,t,n){var r;return r=Ce(function(){e.removed?clearInterval(r):t()},n)},debounce:xe,throttle:xe,clearInterval:function(e){return clearInterval(e)},clearTimeout:function(e){return clearTimeout(e)}},Ne=/^(?:mouse|contextmenu)|click/,Ee={keyLocation:1,layerX:1,layerY:1,returnValue:1,webkitMovementX:1,webkitMovementY:1,keyIdentifier:1},Se=function(){return!1},ke=function(){return!0},Te=function(e,t,n,r){e.addEventListener?e.addEventListener(t,n,r||!1):e.attachEvent&&e.attachEvent("on"+t,n)},Ae=function(e,t,n,r){e.removeEventListener?e.removeEventListener(t,n,r||!1):e.detachEvent&&e.detachEvent("on"+t,n)},Re=function(e,t){var n,r,o,i,a,u,s=t||{};for(n in e)Ee[n]||(s[n]=e[n]);if(s.target||(s.target=s.srcElement||document),ve.experimentalShadowDom&&(s.target=(r=e,o=s.target,a=o,(i=r.path)&&0<i.length&&(a=i[0]),r.composedPath&&(i=r.composedPath())&&0<i.length&&(a=i[0]),a)),e&&Ne.test(e.type)&&e.pageX===undefined&&e.clientX!==undefined){var c=s.target.ownerDocument||document,l=c.documentElement,f=c.body;s.pageX=e.clientX+(l&&l.scrollLeft||f&&f.scrollLeft||0)-(l&&l.clientLeft||f&&f.clientLeft||0),s.pageY=e.clientY+(l&&l.scrollTop||f&&f.scrollTop||0)-(l&&l.clientTop||f&&f.clientTop||0)}return s.preventDefault=function(){s.isDefaultPrevented=ke,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},s.stopPropagation=function(){s.isPropagationStopped=ke,e&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)},!(s.stopImmediatePropagation=function(){s.isImmediatePropagationStopped=ke,s.stopPropagation()})==((u=s).isDefaultPrevented===ke||u.isDefaultPrevented===Se)&&(s.isDefaultPrevented=Se,s.isPropagationStopped=Se,s.isImmediatePropagationStopped=Se),"undefined"==typeof s.metaKey&&(s.metaKey=!1),s},_e=function(e,t,n){var r=e.document,o={type:"ready"};if(n.domLoaded)t(o);else{var i=function(){return"complete"===r.readyState||"interactive"===r.readyState&&r.body},a=function(){n.domLoaded||(n.domLoaded=!0,t(o))},u=function(){i()&&(Ae(r,"readystatechange",u),a())},s=function(){try{r.documentElement.doScroll("left")}catch(e){return void we.setTimeout(s)}a()};!r.addEventListener||ve.ie&&ve.ie<11?(Te(r,"readystatechange",u),r.documentElement.doScroll&&e.self===e.top&&s()):i()?a():Te(e,"DOMContentLoaded",a),Te(e,"load",a)}},Be=function(){var m,p,g,h,v,y=this,b={};p="mce-data-"+(+new Date).toString(32),h="onmouseenter"in document.documentElement,g="onfocusin"in document.documentElement,v={mouseenter:"mouseover",mouseleave:"mouseout"},m=1,y.domLoaded=!1,y.events=b;var C=function(e,t){var n,r,o,i,a=b[t];if(n=a&&a[e.type])for(r=0,o=n.length;r<o;r++)if((i=n[r])&&!1===i.func.call(i.scope,e)&&e.preventDefault(),e.isImmediatePropagationStopped())return};y.bind=function(e,t,n,r){var o,i,a,u,s,c,l,f=window,d=function(e){C(Re(e||f.event),o)};if(e&&3!==e.nodeType&&8!==e.nodeType){for(e[p]?o=e[p]:(o=m++,e[p]=o,b[o]={}),r=r||e,a=(t=t.split(" ")).length;a--;)c=d,s=l=!1,"DOMContentLoaded"===(u=t[a])&&(u="ready"),y.domLoaded&&"ready"===u&&"complete"===e.readyState?n.call(r,Re({type:u})):(h||(s=v[u])&&(c=function(e){var t,n;if(t=e.currentTarget,(n=e.relatedTarget)&&t.contains)n=t.contains(n);else for(;n&&n!==t;)n=n.parentNode;n||((e=Re(e||f.event)).type="mouseout"===e.type?"mouseleave":"mouseenter",e.target=t,C(e,o))}),g||"focusin"!==u&&"focusout"!==u||(l=!0,s="focusin"===u?"focus":"blur",c=function(e){(e=Re(e||f.event)).type="focus"===e.type?"focusin":"focusout",C(e,o)}),(i=b[o][u])?"ready"===u&&y.domLoaded?n({type:u}):i.push({func:n,scope:r}):(b[o][u]=i=[{func:n,scope:r}],i.fakeName=s,i.capture=l,i.nativeHandler=c,"ready"===u?_e(e,c,y):Te(e,s||u,c,l)));return e=i=0,n}},y.unbind=function(e,t,n){var r,o,i,a,u,s;if(!e||3===e.nodeType||8===e.nodeType)return y;if(r=e[p]){if(s=b[r],t){for(i=(t=t.split(" ")).length;i--;)if(o=s[u=t[i]]){if(n)for(a=o.length;a--;)if(o[a].func===n){var c=o.nativeHandler,l=o.fakeName,f=o.capture;(o=o.slice(0,a).concat(o.slice(a+1))).nativeHandler=c,o.fakeName=l,o.capture=f,s[u]=o}n&&0!==o.length||(delete s[u],Ae(e,o.fakeName||u,o.nativeHandler,o.capture))}}else{for(u in s)o=s[u],Ae(e,o.fakeName||u,o.nativeHandler,o.capture);s={}}for(u in s)return y;delete b[r];try{delete e[p]}catch(d){e[p]=null}}return y},y.fire=function(e,t,n){var r;if(!e||3===e.nodeType||8===e.nodeType)return y;for((n=Re(null,n)).type=t,n.target=e;(r=e[p])&&C(n,r),(e=e.parentNode||e.ownerDocument||e.defaultView||e.parentWindow)&&!n.isPropagationStopped(););return y},y.clean=function(e){var t,n,r=y.unbind;if(!e||3===e.nodeType||8===e.nodeType)return y;if(e[p]&&r(e),e.getElementsByTagName||(e=e.document),e&&e.getElementsByTagName)for(r(e),t=(n=e.getElementsByTagName("*")).length;t--;)(e=n[t])[p]&&r(e);return y},y.destroy=function(){b={}},y.cancel=function(e){return e&&(e.preventDefault(),e.stopImmediatePropagation()),!1}};Be.Event=new Be,Be.Event.bind(window,"ready",function(){});var De="sizzle"+-new Date,Oe=window.document,Pe=0,Le=0,Ie=pt(),Me=pt(),Fe=pt(),ze=function(e,t){return e===t&&(ce=!0),0},Ue=typeof undefined,qe={}.hasOwnProperty,Ve=[],He=Ve.pop,je=Ve.push,$e=Ve.push,We=Ve.slice,Ke=Ve.indexOf||function(e){for(var t=0,n=this.length;t<n;t++)if(this[t]===e)return t;return-1},Xe="[\\x20\\t\\r\\n\\f]",Ye="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",Ge="\\["+Xe+"*("+Ye+")(?:"+Xe+"*([*^$|!~]?=)"+Xe+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+Ye+"))|)"+Xe+"*\\]",Je=":("+Ye+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+Ge+")*)|.*)\\)|)",Qe=new RegExp("^"+Xe+"+|((?:^|[^\\\\])(?:\\\\.)*)"+Xe+"+$","g"),Ze=new RegExp("^"+Xe+"*,"+Xe+"*"),et=new RegExp("^"+Xe+"*([>+~]|"+Xe+")"+Xe+"*"),tt=new RegExp("="+Xe+"*([^\\]'\"]*?)"+Xe+"*\\]","g"),nt=new RegExp(Je),rt=new RegExp("^"+Ye+"$"),ot={ID:new RegExp("^#("+Ye+")"),CLASS:new RegExp("^\\.("+Ye+")"),TAG:new RegExp("^("+Ye+"|[*])"),ATTR:new RegExp("^"+Ge),PSEUDO:new RegExp("^"+Je),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+Xe+"*(even|odd|(([+-]|)(\\d*)n|)"+Xe+"*(?:([+-]|)"+Xe+"*(\\d+)|))"+Xe+"*\\)|)","i"),bool:new RegExp("^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$","i"),needsContext:new RegExp("^"+Xe+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+Xe+"*((?:-\\d)?\\d*)"+Xe+"*\\)|)(?=[^-]|$)","i")},it=/^(?:input|select|textarea|button)$/i,at=/^h\d$/i,ut=/^[^{]+\{\s*\[native \w/,st=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ct=/[+~]/,lt=/'|\\/g,ft=new RegExp("\\\\([\\da-f]{1,6}"+Xe+"?|("+Xe+")|.)","ig"),dt=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)};try{$e.apply(Ve=We.call(Oe.childNodes),Oe.childNodes),Ve[Oe.childNodes.length].nodeType}catch(Dw){$e={apply:Ve.length?function(e,t){je.apply(e,We.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}var mt=function(e,t,n,r){var o,i,a,u,s,c,l,f,d,m;if((t?t.ownerDocument||t:Oe)!==fe&&le(t),n=n||[],!e||"string"!=typeof e)return n;if(1!==(u=(t=t||fe).nodeType)&&9!==u)return[];if(me&&!r){if(o=st.exec(e))if(a=o[1]){if(9===u){if(!(i=t.getElementById(a))||!i.parentNode)return n;if(i.id===a)return n.push(i),n}else if(t.ownerDocument&&(i=t.ownerDocument.getElementById(a))&&he(t,i)&&i.id===a)return n.push(i),n}else{if(o[2])return $e.apply(n,t.getElementsByTagName(e)),n;if((a=o[3])&&ee.getElementsByClassName)return $e.apply(n,t.getElementsByClassName(a)),n}if(ee.qsa&&(!pe||!pe.test(e))){if(f=l=De,d=t,m=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){for(c=oe(e),(l=t.getAttribute("id"))?f=l.replace(lt,"\\$&"):t.setAttribute("id",f),f="[id='"+f+"'] ",s=c.length;s--;)c[s]=f+wt(c[s]);d=ct.test(e)&&Ct(t.parentNode)||t,m=c.join(",")}if(m)try{return $e.apply(n,d.querySelectorAll(m)),n}catch(p){}finally{l||t.removeAttribute("id")}}}return ae(e.replace(Qe,"$1"),t,n,r)};function pt(){var r=[];return function e(t,n){return r.push(t+" ")>te.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function gt(e){return e[De]=!0,e}function ht(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||1<<31)-(~e.sourceIndex||1<<31);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function vt(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function yt(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function bt(a){return gt(function(i){return i=+i,gt(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function Ct(e){return e&&typeof e.getElementsByTagName!==Ue&&e}for(Z in ee=mt.support={},re=mt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},le=mt.setDocument=function(e){var t,s=e?e.ownerDocument||e:Oe,n=s.defaultView;return s!==fe&&9===s.nodeType&&s.documentElement?(de=(fe=s).documentElement,me=!re(s),n&&n!==function(e){try{return e.top}catch(t){}return null}(n)&&(n.addEventListener?n.addEventListener("unload",function(){le()},!1):n.attachEvent&&n.attachEvent("onunload",function(){le()})),ee.attributes=!0,ee.getElementsByTagName=!0,ee.getElementsByClassName=ut.test(s.getElementsByClassName),ee.getById=!0,te.find.ID=function(e,t){if(typeof t.getElementById!==Ue&&me){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},te.filter.ID=function(e){var t=e.replace(ft,dt);return function(e){return e.getAttribute("id")===t}},te.find.TAG=ee.getElementsByTagName?function(e,t){if(typeof t.getElementsByTagName!==Ue)return t.getElementsByTagName(e)}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if("*"===e){for(;n=i[o++];)1===n.nodeType&&r.push(n);return r}return i},te.find.CLASS=ee.getElementsByClassName&&function(e,t){if(me)return t.getElementsByClassName(e)},ge=[],pe=[],ee.disconnectedMatch=!0,pe=pe.length&&new RegExp(pe.join("|")),ge=ge.length&&new RegExp(ge.join("|")),t=ut.test(de.compareDocumentPosition),he=t||ut.test(de.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},ze=t?function(e,t){if(e===t)return ce=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!ee.sortDetached&&t.compareDocumentPosition(e)===n?e===s||e.ownerDocument===Oe&&he(Oe,e)?-1:t===s||t.ownerDocument===Oe&&he(Oe,t)?1:se?Ke.call(se,e)-Ke.call(se,t):0:4&n?-1:1)}:function(e,t){if(e===t)return ce=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],u=[t];if(!o||!i)return e===s?-1:t===s?1:o?-1:i?1:se?Ke.call(se,e)-Ke.call(se,t):0;if(o===i)return ht(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;a[r]===u[r];)r++;return r?ht(a[r],u[r]):a[r]===Oe?-1:u[r]===Oe?1:0},s):fe},mt.matches=function(e,t){return mt(e,null,null,t)},mt.matchesSelector=function(e,t){if((e.ownerDocument||e)!==fe&&le(e),t=t.replace(tt,"='$1']"),ee.matchesSelector&&me&&(!ge||!ge.test(t))&&(!pe||!pe.test(t)))try{var n=(void 0).call(e,t);if(n||ee.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(Dw){}return 0<mt(t,fe,null,[e]).length},mt.contains=function(e,t){return(e.ownerDocument||e)!==fe&&le(e),he(e,t)},mt.attr=function(e,t){(e.ownerDocument||e)!==fe&&le(e);var n=te.attrHandle[t.toLowerCase()],r=n&&qe.call(te.attrHandle,t.toLowerCase())?n(e,t,!me):undefined;return r!==undefined?r:ee.attributes||!me?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},mt.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},mt.uniqueSort=function(e){var t,n=[],r=0,o=0;if(ce=!ee.detectDuplicates,se=!ee.sortStable&&e.slice(0),e.sort(ze),ce){for(;t=e[o++];)t===e[o]&&(r=n.push(o));for(;r--;)e.splice(n[r],1)}return se=null,e},ne=mt.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=ne(e)}else if(3===o||4===o)return e.nodeValue}else for(;t=e[r++];)n+=ne(t);return n},(te=mt.selectors={cacheLength:50,createPseudo:gt,match:ot,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(ft,dt),e[3]=(e[3]||e[4]||e[5]||"").replace(ft,dt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||mt.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&mt.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return ot.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&nt.test(n)&&(t=oe(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(ft,dt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=Ie[e+" "];return t||(t=new RegExp("(^|"+Xe+")"+e+"("+Xe+"|$)"))&&Ie(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==Ue&&e.getAttribute("class")||"")})},ATTR:function(n,r,o){return function(e){var t=mt.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===o:"!="===r?t!==o:"^="===r?o&&0===t.indexOf(o):"*="===r?o&&-1<t.indexOf(o):"$="===r?o&&t.slice(-o.length)===o:"~="===r?-1<(" "+t+" ").indexOf(o):"|="===r&&(t===o||t.slice(0,o.length+1)===o+"-"))}},CHILD:function(m,e,t,p,g){var h="nth"!==m.slice(0,3),v="last"!==m.slice(-4),y="of-type"===e;return 1===p&&0===g?function(e){return!!e.parentNode}:function(e,t,n){var r,o,i,a,u,s,c=h!==v?"nextSibling":"previousSibling",l=e.parentNode,f=y&&e.nodeName.toLowerCase(),d=!n&&!y;if(l){if(h){for(;c;){for(i=e;i=i[c];)if(y?i.nodeName.toLowerCase()===f:1===i.nodeType)return!1;s=c="only"===m&&!s&&"nextSibling"}return!0}if(s=[v?l.firstChild:l.lastChild],v&&d){for(u=(r=(o=l[De]||(l[De]={}))[m]||[])[0]===Pe&&r[1],a=r[0]===Pe&&r[2],i=u&&l.childNodes[u];i=++u&&i&&i[c]||(a=u=0)||s.pop();)if(1===i.nodeType&&++a&&i===e){o[m]=[Pe,u,a];break}}else if(d&&(r=(e[De]||(e[De]={}))[m])&&r[0]===Pe)a=r[1];else for(;(i=++u&&i&&i[c]||(a=u=0)||s.pop())&&((y?i.nodeName.toLowerCase()!==f:1!==i.nodeType)||!++a||(d&&((i[De]||(i[De]={}))[m]=[Pe,a]),i!==e)););return(a-=g)===p||a%p==0&&0<=a/p}}},PSEUDO:function(e,i){var t,a=te.pseudos[e]||te.setFilters[e.toLowerCase()]||mt.error("unsupported pseudo: "+e);return a[De]?a(i):1<a.length?(t=[e,e,"",i],te.setFilters.hasOwnProperty(e.toLowerCase())?gt(function(e,t){for(var n,r=a(e,i),o=r.length;o--;)e[n=Ke.call(e,r[o])]=!(t[n]=r[o])}):function(e){return a(e,0,t)}):a}},pseudos:{not:gt(function(e){var r=[],o=[],u=ie(e.replace(Qe,"$1"));return u[De]?gt(function(e,t,n,r){for(var o,i=u(e,null,r,[]),a=e.length;a--;)(o=i[a])&&(e[a]=!(t[a]=o))}):function(e,t,n){return r[0]=e,u(r,null,n,o),!o.pop()}}),has:gt(function(t){return function(e){return 0<mt(t,e).length}}),contains:gt(function(t){return t=t.replace(ft,dt),function(e){return-1<(e.textContent||e.innerText||ne(e)).indexOf(t)}}),lang:gt(function(n){return rt.test(n||"")||mt.error("unsupported lang: "+n),n=n.replace(ft,dt).toLowerCase(),function(e){var t;do{if(t=me?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=window.location&&window.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===de},focus:function(e){return e===fe.activeElement&&(!fe.hasFocus||fe.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return!1===e.disabled},disabled:function(e){return!0===e.disabled},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!te.pseudos.empty(e)},header:function(e){return at.test(e.nodeName)},input:function(e){return it.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:bt(function(){return[0]}),last:bt(function(e,t){return[t-1]}),eq:bt(function(e,t,n){return[n<0?n+t:n]}),even:bt(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:bt(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:bt(function(e,t,n){for(var r=n<0?n+t:n;0<=--r;)e.push(r);return e}),gt:bt(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=te.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})te.pseudos[Z]=vt(Z);for(Z in{submit:!0,reset:!0})te.pseudos[Z]=yt(Z);function xt(){}function wt(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function Nt(a,e,t){var u=e.dir,s=t&&"parentNode"===u,c=Le++;return e.first?function(e,t,n){for(;e=e[u];)if(1===e.nodeType||s)return a(e,t,n)}:function(e,t,n){var r,o,i=[Pe,c];if(n){for(;e=e[u];)if((1===e.nodeType||s)&&a(e,t,n))return!0}else for(;e=e[u];)if(1===e.nodeType||s){if((r=(o=e[De]||(e[De]={}))[u])&&r[0]===Pe&&r[1]===c)return i[2]=r[2];if((o[u]=i)[2]=a(e,t,n))return!0}}}function Et(o){return 1<o.length?function(e,t,n){for(var r=o.length;r--;)if(!o[r](e,t,n))return!1;return!0}:o[0]}function St(e,t,n,r,o){for(var i,a=[],u=0,s=e.length,c=null!=t;u<s;u++)(i=e[u])&&(n&&!n(i,r,o)||(a.push(i),c&&t.push(u)));return a}function kt(m,p,g,h,v,e){return h&&!h[De]&&(h=kt(h)),v&&!v[De]&&(v=kt(v,e)),gt(function(e,t,n,r){var o,i,a,u=[],s=[],c=t.length,l=e||function(e,t,n){for(var r=0,o=t.length;r<o;r++)mt(e,t[r],n);return n}(p||"*",n.nodeType?[n]:n,[]),f=!m||!e&&p?l:St(l,u,m,n,r),d=g?v||(e?m:c||h)?[]:t:f;if(g&&g(f,d,n,r),h)for(o=St(d,s),h(o,[],n,r),i=o.length;i--;)(a=o[i])&&(d[s[i]]=!(f[s[i]]=a));if(e){if(v||m){if(v){for(o=[],i=d.length;i--;)(a=d[i])&&o.push(f[i]=a);v(null,d=[],o,r)}for(i=d.length;i--;)(a=d[i])&&-1<(o=v?Ke.call(e,a):u[i])&&(e[o]=!(t[o]=a))}}else d=St(d===t?d.splice(c,d.length):d),v?v(null,t,d,r):$e.apply(t,d)})}function Tt(e){for(var r,t,n,o=e.length,i=te.relative[e[0].type],a=i||te.relative[" "],u=i?1:0,s=Nt(function(e){return e===r},a,!0),c=Nt(function(e){return-1<Ke.call(r,e)},a,!0),l=[function(e,t,n){return!i&&(n||t!==ue)||((r=t).nodeType?s(e,t,n):c(e,t,n))}];u<o;u++)if(t=te.relative[e[u].type])l=[Nt(Et(l),t)];else{if((t=te.filter[e[u].type].apply(null,e[u].matches))[De]){for(n=++u;n<o&&!te.relative[e[n].type];n++);return kt(1<u&&Et(l),1<u&&wt(e.slice(0,u-1).concat({value:" "===e[u-2].type?"*":""})).replace(Qe,"$1"),t,u<n&&Tt(e.slice(u,n)),n<o&&Tt(e=e.slice(n)),n<o&&wt(e))}l.push(t)}return Et(l)}xt.prototype=te.filters=te.pseudos,te.setFilters=new xt,oe=mt.tokenize=function(e,t){var n,r,o,i,a,u,s,c=Me[e+" "];if(c)return t?0:c.slice(0);for(a=e,u=[],s=te.preFilter;a;){for(i in n&&!(r=Ze.exec(a))||(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=et.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(Qe," ")}),a=a.slice(n.length)),te.filter)!(r=ot[i].exec(a))||s[i]&&!(r=s[i](r))||(n=r.shift(),o.push({value:n,type:i,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?mt.error(e):Me(e,u).slice(0)},ie=mt.compile=function(e,t){var n,h,v,y,b,r,o=[],i=[],a=Fe[e+" "];if(!a){for(t||(t=oe(e)),n=t.length;n--;)(a=Tt(t[n]))[De]?o.push(a):i.push(a);(a=Fe(e,(h=i,y=0<(v=o).length,b=0<h.length,r=function(e,t,n,r,o){var i,a,u,s=0,c="0",l=e&&[],f=[],d=ue,m=e||b&&te.find.TAG("*",o),p=Pe+=null==d?1:Math.random()||.1,g=m.length;for(o&&(ue=t!==fe&&t);c!==g&&null!=(i=m[c]);c++){if(b&&i){for(a=0;u=h[a++];)if(u(i,t,n)){r.push(i);break}o&&(Pe=p)}y&&((i=!u&&i)&&s--,e&&l.push(i))}if(s+=c,y&&c!==s){for(a=0;u=v[a++];)u(l,f,t,n);if(e){if(0<s)for(;c--;)l[c]||f[c]||(f[c]=He.call(r));f=St(f)}$e.apply(r,f),o&&!e&&0<f.length&&1<s+v.length&&mt.uniqueSort(r)}return o&&(Pe=p,ue=d),l},y?gt(r):r))).selector=e}return a},ae=mt.select=function(e,t,n,r){var o,i,a,u,s,c="function"==typeof e&&e,l=!r&&oe(e=c.selector||e);if(n=n||[],1===l.length){if(2<(i=l[0]=l[0].slice(0)).length&&"ID"===(a=i[0]).type&&ee.getById&&9===t.nodeType&&me&&te.relative[i[1].type]){if(!(t=(te.find.ID(a.matches[0].replace(ft,dt),t)||[])[0]))return n;c&&(t=t.parentNode),e=e.slice(i.shift().value.length)}for(o=ot.needsContext.test(e)?0:i.length;o--&&(a=i[o],!te.relative[u=a.type]);)if((s=te.find[u])&&(r=s(a.matches[0].replace(ft,dt),ct.test(i[0].type)&&Ct(t.parentNode)||t))){if(i.splice(o,1),!(e=r.length&&wt(i)))return $e.apply(n,r),n;break}}return(c||ie(e,l))(r,t,!me,n,ct.test(e)&&Ct(t.parentNode)||t),n},ee.sortStable=De.split("").sort(ze).join("")===De,ee.detectDuplicates=!!ce,le(),ee.sortDetached=!0;var At=Array.isArray,Rt=function(e,t,n){var r,o;if(!e)return 0;if(n=n||e,e.length!==undefined){for(r=0,o=e.length;r<o;r++)if(!1===t.call(n,e[r],r,e))return 0}else for(r in e)if(e.hasOwnProperty(r)&&!1===t.call(n,e[r],r,e))return 0;return 1},_t=function(e,t,n){var r,o;for(r=0,o=e.length;r<o;r++)if(t.call(n,e[r],r,e))return r;return-1},Bt={isArray:At,toArray:function(e){var t,n,r=e;if(!At(e))for(r=[],t=0,n=e.length;t<n;t++)r[t]=e[t];return r},each:Rt,map:function(n,r){var o=[];return Rt(n,function(e,t){o.push(r(e,t,n))}),o},filter:function(n,r){var o=[];return Rt(n,function(e,t){r&&!r(e,t,n)||o.push(e)}),o},indexOf:function(e,t){var n,r;if(e)for(n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},reduce:function(e,t,n,r){var o=0;for(arguments.length<3&&(n=e[0]);o<e.length;o++)n=t.call(r,n,e[o],o);return n},findIndex:_t,find:function(e,t,n){var r=_t(e,t,n);return-1!==r?e[r]:undefined},last:function(e){return e[e.length-1]}},Dt=/^\s*|\s*$/g,Ot=function(e){return null===e||e===undefined?"":(""+e).replace(Dt,"")},Pt=function(e,t){return t?!("array"!==t||!Bt.isArray(e))||typeof e===t:e!==undefined},Lt=function(e,n,r,o){o=o||this,e&&(r&&(e=e[r]),Bt.each(e,function(e,t){if(!1===n.call(o,e,t,r))return!1;Lt(e,n,r,o)}))},It={trim:Ot,isArray:Bt.isArray,is:Pt,toArray:Bt.toArray,makeMap:function(e,t,n){var r;for(t=t||",","string"==typeof(e=e||[])&&(e=e.split(t)),n=n||{},r=e.length;r--;)n[e[r]]={};return n},each:Bt.each,map:Bt.map,grep:Bt.filter,inArray:Bt.indexOf,hasOwn:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},extend:function(e,t){for(var n,r,o,i=[],a=2;a<arguments.length;a++)i[a-2]=arguments[a];var u,s=arguments;for(n=1,r=s.length;n<r;n++)for(o in t=s[n])t.hasOwnProperty(o)&&(u=t[o])!==undefined&&(e[o]=u);return e},create:function(e,t,n){var r,o,i,a,u,s=this,c=0;if(e=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(e),i=e[3].match(/(^|\.)(\w+)$/i)[2],!(o=s.createNS(e[3].replace(/\.\w+$/,""),n))[i]){if("static"===e[2])return o[i]=t,void(this.onCreate&&this.onCreate(e[2],e[3],o[i]));t[i]||(t[i]=function(){},c=1),o[i]=t[i],s.extend(o[i].prototype,t),e[5]&&(r=s.resolve(e[5]).prototype,a=e[5].match(/\.(\w+)$/i)[1],u=o[i],o[i]=c?function(){return r[a].apply(this,arguments)}:function(){return this.parent=r[a],u.apply(this,arguments)},o[i].prototype[i]=o[i],s.each(r,function(e,t){o[i].prototype[t]=r[t]}),s.each(t,function(e,t){r[t]?o[i].prototype[t]=function(){return this.parent=r[t],e.apply(this,arguments)}:t!==i&&(o[i].prototype[t]=e)})),s.each(t["static"],function(e,t){o[i][t]=e})}},walk:Lt,createNS:function(e,t){var n,r;for(t=t||window,e=e.split("."),n=0;n<e.length;n++)t[r=e[n]]||(t[r]={}),t=t[r];return t},resolve:function(e,t){var n,r;for(t=t||window,n=0,r=(e=e.split(".")).length;n<r&&(t=t[e[n]]);n++);return t},explode:function(e,t){return!e||Pt(e,"array")?e:Bt.map(e.split(t||","),Ot)},_addCacheSuffix:function(e){var t=ve.cacheSuffix;return t&&(e+=(-1===e.indexOf("?")?"?":"&")+t),e}},Mt=document,Ft=Array.prototype.push,zt=Array.prototype.slice,Ut=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,qt=Be.Event,Vt=It.makeMap("children,contents,next,prev"),Ht=function(e){return void 0!==e},jt=function(e){return"string"==typeof e},$t=function(e,t){var n,r,o;for(o=(t=t||Mt).createElement("div"),n=t.createDocumentFragment(),o.innerHTML=e;r=o.firstChild;)n.appendChild(r);return n},Wt=function(e,t,n,r){var o;if(jt(t))t=$t(t,un(e[0]));else if(t.length&&!t.nodeType){if(t=tn.makeArray(t),r)for(o=t.length-1;0<=o;o--)Wt(e,t[o],n,r);else for(o=0;o<t.length;o++)Wt(e,t[o],n,r);return e}if(t.nodeType)for(o=e.length;o--;)n.call(e[o],t);return e},Kt=function(e,t){return e&&t&&-1!==(" "+e.className+" ").indexOf(" "+t+" ")},Xt=function(e,t,n){var r,o;return t=tn(t)[0],e.each(function(){var e=this;n&&r===e.parentNode||(r=e.parentNode,o=t.cloneNode(!1),e.parentNode.insertBefore(o,e)),o.appendChild(e)}),e},Yt=It.makeMap("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"," "),Gt=It.makeMap("checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected"," "),Jt={"for":"htmlFor","class":"className",readonly:"readOnly"},Qt={"float":"cssFloat"},Zt={},en={},tn=function(e,t){return new tn.fn.init(e,t)},nn=/^\s*|\s*$/g,rn=function(e){return null===e||e===undefined?"":(""+e).replace(nn,"")},on=function(e,t){var n,r,o,i;if(e)if((n=e.length)===undefined){for(r in e)if(e.hasOwnProperty(r)&&(i=e[r],!1===t.call(i,r,i)))break}else for(o=0;o<n&&(i=e[o],!1!==t.call(i,o,i));o++);return e},an=function(e,n){var r=[];return on(e,function(e,t){n(t,e)&&r.push(t)}),r},un=function(e){return e?9===e.nodeType?e:e.ownerDocument:Mt};tn.fn=tn.prototype={constructor:tn,selector:"",context:null,length:0,init:function(e,t){var n,r,o=this;if(!e)return o;if(e.nodeType)return o.context=o[0]=e,o.length=1,o;if(t&&t.nodeType)o.context=t;else{if(t)return tn(e).attr(t);o.context=t=document}if(jt(e)){if(!(n="<"===(o.selector=e).charAt(0)&&">"===e.charAt(e.length-1)&&3<=e.length?[null,e,null]:Ut.exec(e)))return tn(t).find(e);if(n[1])for(r=$t(e,un(t)).firstChild;r;)Ft.call(o,r),r=r.nextSibling;else{if(!(r=un(t).getElementById(n[2])))return o;if(r.id!==n[2])return o.find(e);o.length=1,o[0]=r}}else this.add(e,!1);return o},toArray:function(){return It.toArray(this)},add:function(e,t){var n,r,o=this;if(jt(e))return o.add(tn(e));if(!1!==t)for(n=tn.unique(o.toArray().concat(tn.makeArray(e))),o.length=n.length,r=0;r<n.length;r++)o[r]=n[r];else Ft.apply(o,tn.makeArray(e));return o},attr:function(t,n){var e,r=this;if("object"==typeof t)on(t,function(e,t){r.attr(e,t)});else{if(!Ht(n)){if(r[0]&&1===r[0].nodeType){if((e=Zt[t])&&e.get)return e.get(r[0],t);if(Gt[t])return r.prop(t)?t:undefined;null===(n=r[0].getAttribute(t,2))&&(n=undefined)}return n}this.each(function(){var e;if(1===this.nodeType){if((e=Zt[t])&&e.set)return void e.set(this,n);null===n?this.removeAttribute(t,2):this.setAttribute(t,n,2)}})}return r},removeAttr:function(e){return this.attr(e,null)},prop:function(e,t){var n=this;if("object"==typeof(e=Jt[e]||e))on(e,function(e,t){n.prop(e,t)});else{if(!Ht(t))return n[0]&&n[0].nodeType&&e in n[0]?n[0][e]:t;this.each(function(){1===this.nodeType&&(this[e]=t)})}return n},css:function(n,r){var e,o,i=this,t=function(e){return e.replace(/-(\D)/g,function(e,t){return t.toUpperCase()})},a=function(e){return e.replace(/[A-Z]/g,function(e){return"-"+e})};if("object"==typeof n)on(n,function(e,t){i.css(e,t)});else if(Ht(r))n=t(n),"number"!=typeof r||Yt[n]||(r=r.toString()+"px"),i.each(function(){var e=this.style;if((o=en[n])&&o.set)o.set(this,r);else{try{this.style[Qt[n]||n]=r}catch(t){}null!==r&&""!==r||(e.removeProperty?e.removeProperty(a(n)):e.removeAttribute(n))}});else{if(e=i[0],(o=en[n])&&o.get)return o.get(e);if(!e.ownerDocument.defaultView)return e.currentStyle?e.currentStyle[t(n)]:"";try{return e.ownerDocument.defaultView.getComputedStyle(e,null).getPropertyValue(a(n))}catch(u){return undefined}}return i},remove:function(){for(var e,t=this.length;t--;)e=this[t],qt.clean(e),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var e,t=this.length;t--;)for(e=this[t];e.firstChild;)e.removeChild(e.firstChild);return this},html:function(e){var t,n=this;if(Ht(e)){t=n.length;try{for(;t--;)n[t].innerHTML=e}catch(r){tn(n[t]).empty().append(e)}return n}return n[0]?n[0].innerHTML:""},text:function(e){var t,n=this;if(Ht(e)){for(t=n.length;t--;)"innerText"in n[t]?n[t].innerText=e:n[0].textContent=e;return n}return n[0]?n[0].innerText||n[0].textContent:""},append:function(){return Wt(this,arguments,function(e){(1===this.nodeType||this.host&&1===this.host.nodeType)&&this.appendChild(e)})},prepend:function(){return Wt(this,arguments,function(e){(1===this.nodeType||this.host&&1===this.host.nodeType)&&this.insertBefore(e,this.firstChild)},!0)},before:function(){return this[0]&&this[0].parentNode?Wt(this,arguments,function(e){this.parentNode.insertBefore(e,this)}):this},after:function(){return this[0]&&this[0].parentNode?Wt(this,arguments,function(e){this.parentNode.insertBefore(e,this.nextSibling)},!0):this},appendTo:function(e){return tn(e).append(this),this},prependTo:function(e){return tn(e).prepend(this),this},replaceWith:function(e){return this.before(e).remove()},wrap:function(e){return Xt(this,e)},wrapAll:function(e){return Xt(this,e,!0)},wrapInner:function(e){return this.each(function(){tn(this).contents().wrapAll(e)}),this},unwrap:function(){return this.parent().each(function(){tn(this).replaceWith(this.childNodes)})},clone:function(){var e=[];return this.each(function(){e.push(this.cloneNode(!0))}),tn(e)},addClass:function(e){return this.toggleClass(e,!0)},removeClass:function(e){return this.toggleClass(e,!1)},toggleClass:function(o,i){var e=this;return"string"!=typeof o||(-1!==o.indexOf(" ")?on(o.split(" "),function(){e.toggleClass(this,i)}):e.each(function(e,t){var n,r;(r=Kt(t,o))!==i&&(n=t.className,r?t.className=rn((" "+n+" ").replace(" "+o+" "," ")):t.className+=n?" "+o:o)})),e},hasClass:function(e){return Kt(this[0],e)},each:function(e){return on(this,e)},on:function(e,t){return this.each(function(){qt.bind(this,e,t)})},off:function(e,t){return this.each(function(){qt.unbind(this,e,t)})},trigger:function(e){return this.each(function(){"object"==typeof e?qt.fire(this,e.type,e):qt.fire(this,e)})},show:function(){return this.css("display","")},hide:function(){return this.css("display","none")},slice:function(){return new tn(zt.apply(this,arguments))},eq:function(e){return-1===e?this.slice(e):this.slice(e,+e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},find:function(e){var t,n,r=[];for(t=0,n=this.length;t<n;t++)tn.find(e,this[t],r);return tn(r)},filter:function(n){return tn("function"==typeof n?an(this.toArray(),function(e,t){return n(t,e)}):tn.filter(n,this.toArray()))},closest:function(n){var r=[];return n instanceof tn&&(n=n[0]),this.each(function(e,t){for(;t;){if("string"==typeof n&&tn(t).is(n)){r.push(t);break}if(t===n){r.push(t);break}t=t.parentNode}}),tn(r)},offset:function(e){var t,n,r,o,i=0,a=0;return e?this.css(e):((t=this[0])&&(r=(n=t.ownerDocument).documentElement,t.getBoundingClientRect&&(i=(o=t.getBoundingClientRect()).left+(r.scrollLeft||n.body.scrollLeft)-r.clientLeft,a=o.top+(r.scrollTop||n.body.scrollTop)-r.clientTop)),{left:i,top:a})},push:Ft,sort:[].sort,splice:[].splice},It.extend(tn,{extend:It.extend,makeArray:function(e){return(t=e)&&t===t.window||e.nodeType?[e]:It.toArray(e);var t},inArray:function(e,t){var n;if(t.indexOf)return t.indexOf(e);for(n=t.length;n--;)if(t[n]===e)return n;return-1},isArray:It.isArray,each:on,trim:rn,grep:an,find:mt,expr:mt.selectors,unique:mt.uniqueSort,text:mt.getText,contains:mt.contains,filter:function(e,t,n){var r=t.length;for(n&&(e=":not("+e+")");r--;)1!==t[r].nodeType&&t.splice(r,1);return t=1===t.length?tn.find.matchesSelector(t[0],e)?[t[0]]:[]:tn.find.matches(e,t)}});var sn=function(e,t,n){var r=[],o=e[t];for("string"!=typeof n&&n instanceof tn&&(n=n[0]);o&&9!==o.nodeType;){if(n!==undefined){if(o===n)break;if("string"==typeof n&&tn(o).is(n))break}1===o.nodeType&&r.push(o),o=o[t]}return r},cn=function(e,t,n,r){var o=[];for(r instanceof tn&&(r=r[0]);e;e=e[t])if(!n||e.nodeType===n){if(r!==undefined){if(e===r)break;if("string"==typeof r&&tn(e).is(r))break}o.push(e)}return o},ln=function(e,t,n){for(e=e[t];e;e=e[t])if(e.nodeType===n)return e;return null};on({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return sn(e,"parentNode")},next:function(e){return ln(e,"nextSibling",1)},prev:function(e){return ln(e,"previousSibling",1)},children:function(e){return cn(e.firstChild,"nextSibling",1)},contents:function(e){return It.toArray(("iframe"===e.nodeName?e.contentDocument||e.contentWindow.document:e).childNodes)}},function(e,r){tn.fn[e]=function(t){var n=[];return this.each(function(){var e=r.call(n,this,t,n);e&&(tn.isArray(e)?n.push.apply(n,e):n.push(e))}),1<this.length&&(Vt[e]||(n=tn.unique(n)),0===e.indexOf("parents")&&(n=n.reverse())),n=tn(n),t?n.filter(t):n}}),on({parentsUntil:function(e,t){return sn(e,"parentNode",t)},nextUntil:function(e,t){return cn(e,"nextSibling",1,t).slice(1)},prevUntil:function(e,t){return cn(e,"previousSibling",1,t).slice(1)}},function(r,o){tn.fn[r]=function(t,e){var n=[];return this.each(function(){var e=o.call(n,this,t,n);e&&(tn.isArray(e)?n.push.apply(n,e):n.push(e))}),1<this.length&&(n=tn.unique(n),0!==r.indexOf("parents")&&"prevUntil"!==r||(n=n.reverse())),n=tn(n),e?n.filter(e):n}}),tn.fn.is=function(e){return!!e&&0<this.filter(e).length},tn.fn.init.prototype=tn.fn,tn.overrideDefaults=function(n){var r,o=function(e,t){return r=r||n(),0===arguments.length&&(e=r.element),t||(t=r.context),new o.fn.init(e,t)};return tn.extend(o,this),o};var fn=function(n,r,e){on(e,function(e,t){n[e]=n[e]||{},n[e][r]=t})};ve.ie&&ve.ie<8&&(fn(Zt,"get",{maxlength:function(e){var t=e.maxLength;return 2147483647===t?undefined:t},size:function(e){var t=e.size;return 20===t?undefined:t},"class":function(e){return e.className},style:function(e){var t=e.style.cssText;return 0===t.length?undefined:t}}),fn(Zt,"set",{"class":function(e,t){e.className=t},style:function(e,t){e.style.cssText=t}})),ve.ie&&ve.ie<9&&(Qt["float"]="styleFloat",fn(en,"set",{opacity:function(e,t){var n=e.style;null===t||""===t?n.removeAttribute("filter"):(n.zoom=1,n.filter="alpha(opacity="+100*t+")")}})),tn.attrHooks=Zt,tn.cssHooks=en;var dn,mn=function(e){var t,n=!1;return function(){return n||(n=!0,t=e.apply(null,arguments)),t}},pn=function(e,t){var n=function(e,t){for(var n=0;n<e.length;n++){var r=e[n];if(r.test(t))return r}return undefined}(e,t);if(!n)return{major:0,minor:0};var r=function(e){return Number(t.replace(n,"$"+e))};return hn(r(1),r(2))},gn=function(){return hn(0,0)},hn=function(e,t){return{major:e,minor:t}},vn={nu:hn,detect:function(e,t){var n=String(t).toLowerCase();return 0===e.length?gn():pn(e,n)},unknown:gn},yn="Firefox",bn=function(e,t){return function(){return t===e}},Cn=function(e){var t=e.current;return{current:t,version:e.version,isEdge:bn("Edge",t),isChrome:bn("Chrome",t),isIE:bn("IE",t),isOpera:bn("Opera",t),isFirefox:bn(yn,t),isSafari:bn("Safari",t)}},xn={unknown:function(){return Cn({current:undefined,version:vn.unknown()})},nu:Cn,edge:V.constant("Edge"),chrome:V.constant("Chrome"),ie:V.constant("IE"),opera:V.constant("Opera"),firefox:V.constant(yn),safari:V.constant("Safari")},wn="Windows",Nn="Android",En="Solaris",Sn="FreeBSD",kn=function(e,t){return function(){return t===e}},Tn=function(e){var t=e.current;return{current:t,version:e.version,isWindows:kn(wn,t),isiOS:kn("iOS",t),isAndroid:kn(Nn,t),isOSX:kn("OSX",t),isLinux:kn("Linux",t),isSolaris:kn(En,t),isFreeBSD:kn(Sn,t)}},An={unknown:function(){return Tn({current:undefined,version:vn.unknown()})},nu:Tn,windows:V.constant(wn),ios:V.constant("iOS"),android:V.constant(Nn),linux:V.constant("Linux"),osx:V.constant("OSX"),solaris:V.constant(En),freebsd:V.constant(Sn)},Rn=function(e,t){var n=String(t).toLowerCase();return H.find(e,function(e){return e.search(n)})},_n=function(e,n){return Rn(e,n).map(function(e){var t=vn.detect(e.versionRegexes,n);return{current:e.name,version:t}})},Bn=function(e,n){return Rn(e,n).map(function(e){var t=vn.detect(e.versionRegexes,n);return{current:e.name,version:t}})},Dn=function(e,t){return-1!==e.indexOf(t)},On=function(e){return e.replace(/^\s+|\s+$/g,"")},Pn=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,Ln=function(t){return function(e){return Dn(e,t)}},In=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:function(e){return Dn(e,"edge/")&&Dn(e,"chrome")&&Dn(e,"safari")&&Dn(e,"applewebkit")}},{name:"Chrome",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,Pn],search:function(e){return Dn(e,"chrome")&&!Dn(e,"chromeframe")}},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:function(e){return Dn(e,"msie")||Dn(e,"trident")}},{name:"Opera",versionRegexes:[Pn,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:Ln("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:Ln("firefox")},{name:"Safari",versionRegexes:[Pn,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:function(e){return(Dn(e,"safari")||Dn(e,"mobile/"))&&Dn(e,"applewebkit")}}],Mn=[{name:"Windows",search:Ln("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:function(e){return Dn(e,"iphone")||Dn(e,"ipad")},versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:Ln("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"OSX",search:Ln("os x"),versionRegexes:[/.*?os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:Ln("linux"),versionRegexes:[]},{name:"Solaris",search:Ln("sunos"),versionRegexes:[]},{name:"FreeBSD",search:Ln("freebsd"),versionRegexes:[]}],Fn={browsers:V.constant(In),oses:V.constant(Mn)},zn=function(e){var t,n,r,o,i,a,u,s,c,l,f,d=Fn.browsers(),m=Fn.oses(),p=_n(d,e).fold(xn.unknown,xn.nu),g=Bn(m,e).fold(An.unknown,An.nu);return{browser:p,os:g,deviceType:(n=p,r=e,o=(t=g).isiOS()&&!0===/ipad/i.test(r),i=t.isiOS()&&!o,a=t.isAndroid()&&3===t.version.major,u=t.isAndroid()&&4===t.version.major,s=o||a||u&&!0===/mobile/i.test(r),c=t.isiOS()||t.isAndroid(),l=c&&!s,f=n.isSafari()&&t.isiOS()&&!1===/safari/i.test(r),{isiPad:V.constant(o),isiPhone:V.constant(i),isTablet:V.constant(s),isPhone:V.constant(l),isTouch:V.constant(c),isAndroid:t.isAndroid,isiOS:t.isiOS,isWebView:V.constant(f)})}},Un={detect:mn(function(){var e=navigator.userAgent;return zn(e)})},qn=function(e){if(null===e||e===undefined)throw new Error("Node cannot be null or undefined");return{dom:V.constant(e)}},Vn={fromHtml:function(e,t){var n=(t||document).createElement("div");if(n.innerHTML=e,!n.hasChildNodes()||1<n.childNodes.length)throw console.error("HTML does not have a single root node",e),"HTML must have a single root node";return qn(n.childNodes[0])},fromTag:function(e,t){var n=(t||document).createElement(e);return qn(n)},fromText:function(e,t){var n=(t||document).createTextNode(e);return qn(n)},fromDom:qn,fromPoint:function(e,t,n){return A.from(e.dom().elementFromPoint(t,n)).map(qn)}},Hn=8,jn=9,$n=1,Wn=3,Kn=function(e){return e.dom().nodeName.toLowerCase()},Xn=function(e){return e.dom().nodeType},Yn=function(t){return function(e){return Xn(e)===t}},Gn=Yn($n),Jn=Yn(Wn),Qn=Yn(jn),Zn={name:Kn,type:Xn,value:function(e){return e.dom().nodeValue},isElement:Gn,isText:Jn,isDocument:Qn,isComment:function(e){return Xn(e)===Hn||"#comment"===Kn(e)}},er=(dn=Object.keys)===undefined?function(e){var t=[];for(var n in e)e.hasOwnProperty(n)&&t.push(n);return t}:dn,tr=function(e,t){for(var n=er(e),r=0,o=n.length;r<o;r++){var i=n[r];t(e[i],i,e)}},nr=function(r,o){var i={};return tr(r,function(e,t){var n=o(e,t,r);i[n.k]=n.v}),i},rr=function(e,n){var r=[];return tr(e,function(e,t){r.push(n(e,t))}),r},or=function(e){return rr(e,function(e){return e})},ir={bifilter:function(e,n){var r={},o={};return tr(e,function(e,t){(n(e,t)?r:o)[t]=e}),{t:r,f:o}},each:tr,map:function(e,r){return nr(e,function(e,t,n){return{k:t,v:r(e,t,n)}})},mapToArray:rr,tupleMap:nr,find:function(e,t){for(var n=er(e),r=0,o=n.length;r<o;r++){var i=n[r],a=e[i];if(t(a,i,e))return A.some(a)}return A.none()},keys:er,values:or,size:function(e){return or(e).length}},ar=function(e,t,n){if(!(k.isString(n)||k.isBoolean(n)||k.isNumber(n)))throw console.error("Invalid call to Attr.set. Key ",t,":: Value ",n,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,n+"")},ur=function(e,t,n){ar(e.dom(),t,n)},sr=function(e,t){var n=e.dom().getAttribute(t);return null===n?undefined:n},cr=function(e,t){var n=e.dom();return!(!n||!n.hasAttribute)&&n.hasAttribute(t)},lr={clone:function(e){return H.foldl(e.dom().attributes,function(e,t){return e[t.name]=t.value,e},{})},set:ur,setAll:function(e,t){var n=e.dom();ir.each(t,function(e,t){ar(n,t,e)})},get:sr,has:cr,remove:function(e,t){e.dom().removeAttribute(t)},hasNone:function(e){var t=e.dom().attributes;return t===undefined||null===t||0===t.length},transfer:function(o,i,e){Zn.isElement(o)&&Zn.isElement(i)&&H.each(e,function(e){var t,n,r;n=i,cr(t=o,r=e)&&!cr(n,r)&&ur(n,r,sr(t,r))})}},fr=mn(function(){return dr(Vn.fromDom(document))}),dr=function(e){var t=e.dom().body;if(null===t||t===undefined)throw"Body is not available yet";return Vn.fromDom(t)},mr={body:fr,getBody:dr,inBody:function(e){var t=Zn.isText(e)?e.dom().parentNode:e.dom();return t!==undefined&&null!==t&&t.ownerDocument.body.contains(t)}},pr=function(e){return e.style!==undefined},gr=function(e,t,n){if(!k.isString(n))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",n,":: Element ",e),new Error("CSS value must be a string: "+n);pr(e)&&e.style.setProperty(t,n)},hr=function(e,t){return pr(e)?e.style.getPropertyValue(t):""},vr=function(e,t){var n=e.dom(),r=hr(n,t);return A.from(r).filter(function(e){return 0<e.length})},yr=function(e,t){var n=e.dom();ir.each(t,function(e,t){gr(n,t,e)})},br=function(e,t){var n=e.dom(),r=window.getComputedStyle(n).getPropertyValue(t),o=""!==r||mr.inBody(e)?r:hr(n,t);return null===o?undefined:o},Cr=vr,xr=function(e){return e.slice(0).sort()},wr=function(e,t){throw new Error("All required keys ("+xr(e).join(", ")+") were not specified. Specified keys were: "+xr(t).join(", ")+".")},Nr=function(e){throw new Error("Unsupported keys for object: "+xr(e).join(", "))},Er=function(t,e){if(!k.isArray(e))throw new Error("The "+t+" fields must be an array. Was: "+e+".");H.each(e,function(e){if(!k.isString(e))throw new Error("The value "+e+" in the "+t+" fields was not a string.")})},Sr=function(e){var n=xr(e);H.find(n,function(e,t){return t<n.length-1&&e===n[t+1]}).each(function(e){throw new Error("The field: "+e+" occurs more than once in the combined fields: ["+n.join(", ")+"].")})},kr={immutable:function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return function(){for(var n=[],e=0;e<arguments.length;e++)n[e]=arguments[e];if(t.length!==n.length)throw new Error('Wrong number of arguments to struct. Expected "['+t.length+']", got '+n.length+" arguments");var r={};return H.each(t,function(e,t){r[e]=V.constant(n[t])}),r}},immutableBag:function(o,i){var a=o.concat(i);if(0===a.length)throw new Error("You must specify at least one required or optional field.");return Er("required",o),Er("optional",i),Sr(a),function(t){var n=ir.keys(t);H.forall(o,function(e){return H.contains(n,e)})||wr(o,n);var e=H.filter(n,function(e){return!H.contains(a,e)});0<e.length&&Nr(e);var r={};return H.each(o,function(e){r[e]=V.constant(t[e])}),H.each(i,function(e){r[e]=V.constant(Object.prototype.hasOwnProperty.call(t,e)?A.some(t[e]):A.none())}),r}}},Tr=function(e,t){for(var n=[],r=function(e){return n.push(e),t(e)},o=t(e);(o=o.bind(r)).isSome(););return n},Ar=function(){return W.getOrDie("Node")},Rr=function(e,t,n){return 0!=(e.compareDocumentPosition(t)&n)},_r=function(e,t){return Rr(e,t,Ar().DOCUMENT_POSITION_CONTAINED_BY)},Br=$n,Dr=jn,Or=function(e){return e.nodeType!==Br&&e.nodeType!==Dr||0===e.childElementCount},Pr={all:function(e,t){var n=t===undefined?document:t.dom();return Or(n)?[]:H.map(n.querySelectorAll(e),Vn.fromDom)},is:function(e,t){var n=e.dom();if(n.nodeType!==Br)return!1;if(n.matches!==undefined)return n.matches(t);if(n.msMatchesSelector!==undefined)return n.msMatchesSelector(t);if(n.webkitMatchesSelector!==undefined)return n.webkitMatchesSelector(t);if(n.mozMatchesSelector!==undefined)return n.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")},one:function(e,t){var n=t===undefined?document:t.dom();return Or(n)?A.none():A.from(n.querySelector(e)).map(Vn.fromDom)}},Lr=function(e,t){return e.dom()===t.dom()},Ir=Un.detect().browser.isIE()?function(e,t){return _r(e.dom(),t.dom())}:function(e,t){var n=e.dom(),r=t.dom();return n!==r&&n.contains(r)},Mr={eq:Lr,isEqualNode:function(e,t){return e.dom().isEqualNode(t.dom())},member:function(e,t){return H.exists(t,V.curry(Lr,e))},contains:Ir,is:Pr.is},Fr=function(e){return Vn.fromDom(e.dom().ownerDocument)},zr=function(e){var t=e.dom();return A.from(t.parentNode).map(Vn.fromDom)},Ur=function(e){var t=e.dom();return A.from(t.previousSibling).map(Vn.fromDom)},qr=function(e){var t=e.dom();return A.from(t.nextSibling).map(Vn.fromDom)},Vr=function(e){var t=e.dom();return H.map(t.childNodes,Vn.fromDom)},Hr=function(e,t){var n=e.dom().childNodes;return A.from(n[t]).map(Vn.fromDom)},jr=kr.immutable("element","offset"),$r={owner:Fr,defaultView:function(e){var t=e.dom().ownerDocument.defaultView;return Vn.fromDom(t)},documentElement:function(e){var t=Fr(e);return Vn.fromDom(t.dom().documentElement)},parent:zr,findIndex:function(n){return zr(n).bind(function(e){var t=Vr(e);return H.findIndex(t,function(e){return Mr.eq(n,e)})})},parents:function(e,t){for(var n=k.isFunction(t)?t:V.constant(!1),r=e.dom(),o=[];null!==r.parentNode&&r.parentNode!==undefined;){var i=r.parentNode,a=Vn.fromDom(i);if(o.push(a),!0===n(a))break;r=i}return o},siblings:function(t){return zr(t).map(Vr).map(function(e){return H.filter(e,function(e){return!Mr.eq(t,e)})}).getOr([])},prevSibling:Ur,offsetParent:function(e){var t=e.dom();return A.from(t.offsetParent).map(Vn.fromDom)},prevSiblings:function(e){return H.reverse(Tr(e,Ur))},nextSibling:qr,nextSiblings:function(e){return Tr(e,qr)},children:Vr,child:Hr,firstChild:function(e){return Hr(e,0)},lastChild:function(e){return Hr(e,e.dom().childNodes.length-1)},childNodesCount:function(e){return e.dom().childNodes.length},hasChildNodes:function(e){return e.dom().hasChildNodes()},leaf:function(e,t){var n=Vr(e);return 0<n.length&&t<n.length?jr(n[t],0):jr(e,t)}},Wr=Un.detect().browser,Kr=function(e){return H.find(e,Zn.isElement)},Xr={getPos:function(e,t,n){var r,o,i,a=0,u=0,s=e.ownerDocument;if(n=n||e,t){if(n===e&&t.getBoundingClientRect&&"static"===br(Vn.fromDom(e),"position"))return{x:a=(o=t.getBoundingClientRect()).left+(s.documentElement.scrollLeft||e.scrollLeft)-s.documentElement.clientLeft,y:u=o.top+(s.documentElement.scrollTop||e.scrollTop)-s.documentElement.clientTop};for(r=t;r&&r!==n&&r.nodeType;)a+=r.offsetLeft||0,u+=r.offsetTop||0,r=r.offsetParent;for(r=t.parentNode;r&&r!==n&&r.nodeType;)a-=r.scrollLeft||0,u-=r.scrollTop||0,r=r.parentNode;u+=(i=Vn.fromDom(t),Wr.isFirefox()&&"table"===Zn.name(i)?Kr($r.children(i)).filter(function(e){return"caption"===Zn.name(e)}).bind(function(o){return Kr($r.nextSiblings(o)).map(function(e){var t=e.dom().offsetTop,n=o.dom().offsetTop,r=o.dom().offsetHeight;return t<=n?-r:0})}).getOr(0):0)}return{x:a,y:u}}},Yr=function(e){var n=A.none(),t=[],r=function(e){o()?a(e):t.push(e)},o=function(){return n.isSome()},i=function(e){H.each(e,a)},a=function(t){n.each(function(e){setTimeout(function(){t(e)},0)})};return e(function(e){n=A.some(e),i(t),t=[]}),{get:r,map:function(n){return Yr(function(t){r(function(e){t(n(e))})})},isReady:o}},Gr={nu:Yr,pure:function(t){return Yr(function(e){e(t)})}},Jr=function(n){return function(){var e=Array.prototype.slice.call(arguments),t=this;setTimeout(function(){n.apply(t,e)},0)}},Qr=function(t){var e=function(e){t(Jr(e))};return{map:function(r){return Qr(function(n){e(function(e){var t=r(e);n(t)})})},bind:function(n){return Qr(function(t){e(function(e){n(e).get(t)})})},anonBind:function(n){return Qr(function(t){e(function(e){n.get(t)})})},toLazy:function(){return Gr.nu(e)},get:e}},Zr={nu:Qr,pure:function(t){return Qr(function(e){e(t)})}},eo=function(a,e){return e(function(r){var o=[],i=0;0===a.length?r([]):H.each(a,function(e,t){var n;e.get((n=t,function(e){o[n]=e,++i>=a.length&&r(o)}))})})},to=function(e){return eo(e,Zr.nu)},no={par:to,mapM:function(e,t){var n=H.map(e,t);return to(n)},compose:function(t,n){return function(e){return n(e).bind(t)}}},ro=function(n){return{is:function(e){return n===e},isValue:V.always,isError:V.never,getOr:V.constant(n),getOrThunk:V.constant(n),getOrDie:V.constant(n),or:function(e){return ro(n)},orThunk:function(e){return ro(n)},fold:function(e,t){return t(n)},map:function(e){return ro(e(n))},each:function(e){e(n)},bind:function(e){return e(n)},exists:function(e){return e(n)},forall:function(e){return e(n)},toOption:function(){return A.some(n)}}},oo=function(n){return{is:V.never,isValue:V.never,isError:V.always,getOr:V.identity,getOrThunk:function(e){return e()},getOrDie:function(){return V.die(String(n))()},or:function(e){return e},orThunk:function(e){return e()},fold:function(e,t){return e(n)},map:function(e){return oo(n)},each:V.noop,bind:function(e){return oo(n)},exists:V.never,forall:V.always,toOption:A.none}},io={value:ro,error:oo};function ao(e,u){var t=e,n=function(e,t,n,r){var o,i;if(e){if(!r&&e[t])return e[t];if(e!==u){if(o=e[n])return o;for(i=e.parentNode;i&&i!==u;i=i.parentNode)if(o=i[n])return o}}};this.current=function(){return t},this.next=function(e){return t=n(t,"firstChild","nextSibling",e)},this.prev=function(e){return t=n(t,"lastChild","previousSibling",e)},this.prev2=function(e){return t=function(e,t,n,r){var o,i,a;if(e){if(o=e[n],u&&o===u)return;if(o){if(!r)for(a=o[t];a;a=a[t])if(!a[t])return a;return o}if((i=e.parentNode)&&i!==u)return i}}(t,"lastChild","previousSibling",e)}}var uo,so,co,lo=function(t){var n;return function(e){return(n=n||H.mapToObject(t,V.constant(!0))).hasOwnProperty(Zn.name(e))}},fo=lo(["h1","h2","h3","h4","h5","h6"]),mo=lo(["article","aside","details","div","dt","figcaption","footer","form","fieldset","header","hgroup","html","main","nav","section","summary","body","p","dl","multicol","dd","figure","address","center","blockquote","h1","h2","h3","h4","h5","h6","listing","xmp","pre","plaintext","menu","dir","ul","ol","li","hr","table","tbody","thead","tfoot","th","tr","td","caption"]),po=function(e){return Zn.isElement(e)&&!mo(e)},go=function(e){return Zn.isElement(e)&&"br"===Zn.name(e)},ho=lo(["h1","h2","h3","h4","h5","h6","p","div","address","pre","form","blockquote","center","dir","fieldset","header","footer","article","section","hgroup","aside","nav","figure"]),vo=lo(["ul","ol","dl"]),yo=lo(["li","dd","dt"]),bo=lo(["area","base","basefont","br","col","frame","hr","img","input","isindex","link","meta","param","embed","source","wbr","track"]),Co=lo(["thead","tbody","tfoot"]),xo=lo(["td","th"]),wo=lo(["pre","script","textarea","style"]),No=function(t){return function(e){return!!e&&e.nodeType===t}},Eo=No(1),So=function(e){var r=e.toLowerCase().split(" ");return function(e){var t,n;if(e&&e.nodeType)for(n=e.nodeName.toLowerCase(),t=0;t<r.length;t++)if(n===r[t])return!0;return!1}},ko=function(t){return function(e){if(Eo(e)){if(e.contentEditable===t)return!0;if(e.getAttribute("data-mce-contenteditable")===t)return!0}return!1}},To=No(3),Ao=No(8),Ro=No(9),_o=So("br"),Bo=ko("true"),Do=ko("false"),Oo={isText:To,isElement:Eo,isComment:Ao,isDocument:Ro,isBr:_o,isContentEditableTrue:Bo,isContentEditableFalse:Do,matchNodeNames:So,hasPropValue:function(t,n){return function(e){return Eo(e)&&e[t]===n}},hasAttribute:function(t,e){return function(e){return Eo(e)&&e.hasAttribute(t)}},hasAttributeValue:function(t,n){return function(e){return Eo(e)&&e.getAttribute(t)===n}},matchStyleValues:function(r,e){var o=e.toLowerCase().split(" ");return function(e){var t;if(Eo(e))for(t=0;t<o.length;t++){var n=e.ownerDocument.defaultView.getComputedStyle(e,null);if((n?n.getPropertyValue(r):null)===o[t])return!0}return!1}},isBogus:function(e){return Eo(e)&&e.hasAttribute("data-mce-bogus")},isBogusAll:function(e){return Eo(e)&&"all"===e.getAttribute("data-mce-bogus")},isTable:function(e){return Eo(e)&&"TABLE"===e.tagName}},Po=function(e){return e&&"SPAN"===e.tagName&&"bookmark"===e.getAttribute("data-mce-type")},Lo=function(e,t){var n,r=t.childNodes;if(!Oo.isElement(t)||!Po(t)){for(n=r.length-1;0<=n;n--)Lo(e,r[n]);if(!1===Oo.isDocument(t)){if(Oo.isText(t)&&0<t.nodeValue.length){var o=It.trim(t.nodeValue).length;if(e.isBlock(t.parentNode)||0<o)return;if(0===o&&(a=(i=t).previousSibling&&"SPAN"===i.previousSibling.nodeName,u=i.nextSibling&&"SPAN"===i.nextSibling.nodeName,a&&u))return}else if(Oo.isElement(t)&&(1===(r=t.childNodes).length&&Po(r[0])&&t.parentNode.insertBefore(r[0],t),r.length||bo(Vn.fromDom(t))))return;e.remove(t)}var i,a,u;return t}},Io={trimNode:Lo},Mo=It.makeMap,Fo=/[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,zo=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,Uo=/[<>&\"\']/g,qo=/&#([a-z0-9]+);?|&([a-z0-9]+);/gi,Vo={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"};so={'"':""","'":"'","<":"<",">":">","&":"&","`":"`"},co={"<":"<",">":">","&":"&",""":'"',"'":"'"};var Ho=function(e,t){var n,r,o,i={};if(e){for(e=e.split(","),t=t||10,n=0;n<e.length;n+=2)r=String.fromCharCode(parseInt(e[n],t)),so[r]||(o="&"+e[n+1]+";",i[r]=o,i[o]=r);return i}};uo=Ho("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);var jo=function(e,t){return e.replace(t?Fo:zo,function(e){return so[e]||e})},$o=function(e,t){return e.replace(t?Fo:zo,function(e){return 1<e.length?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":so[e]||"&#"+e.charCodeAt(0)+";"})},Wo=function(e,t,n){return n=n||uo,e.replace(t?Fo:zo,function(e){return so[e]||n[e]||e})},Ko={encodeRaw:jo,encodeAllRaw:function(e){return(""+e).replace(Uo,function(e){return so[e]||e})},encodeNumeric:$o,encodeNamed:Wo,getEncodeFunc:function(e,t){var n=Ho(t)||uo,r=Mo(e.replace(/\+/g,","));return r.named&&r.numeric?function(e,t){return e.replace(t?Fo:zo,function(e){return so[e]!==undefined?so[e]:n[e]!==undefined?n[e]:1<e.length?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":"&#"+e.charCodeAt(0)+";"})}:r.named?t?function(e,t){return Wo(e,t,n)}:Wo:r.numeric?$o:jo},decode:function(e){return e.replace(qo,function(e,t){return t?65535<(t="x"===t.charAt(0).toLowerCase()?parseInt(t.substr(1),16):parseInt(t,10))?(t-=65536,String.fromCharCode(55296+(t>>10),56320+(1023&t))):Vo[t]||String.fromCharCode(t):co[e]||uo[e]||(n=e,(r=Vn.fromTag("div").dom()).innerHTML=n,r.textContent||r.innerText||n);var n,r})}},Xo={},Yo={},Go=It.makeMap,Jo=It.each,Qo=It.extend,Zo=It.explode,ei=It.inArray,ti=function(e,t){return(e=It.trim(e))?e.split(t||" "):[]},ni=function(e){var u,t,n,r,o,i,s={},a=function(e,t,n){var r,o,i,a=function(e,t){var n,r,o={};for(n=0,r=e.length;n<r;n++)o[e[n]]=t||{};return o};for(t=t||"","string"==typeof(n=n||[])&&(n=ti(n)),r=(e=ti(e)).length;r--;)i={attributes:a(o=ti([u,t].join(" "))),attributesOrder:o,children:a(n,Yo)},s[e[r]]=i},c=function(e,t){var n,r,o,i;for(n=(e=ti(e)).length,t=ti(t);n--;)for(r=s[e[n]],o=0,i=t.length;o<i;o++)r.attributes[t[o]]={},r.attributesOrder.push(t[o])};return Xo[e]?Xo[e]:(u="id accesskey class dir lang style tabindex title role",t="address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul",n="a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment","html4"!==e&&(u+=" contenteditable contextmenu draggable dropzone hidden spellcheck translate",t+=" article aside details dialog figure header footer hgroup section nav",n+=" audio canvas command datalist mark meter output picture progress time wbr video ruby bdi keygen"),"html5-strict"!==e&&(u+=" xml:lang",n=[n,i="acronym applet basefont big font strike tt"].join(" "),Jo(ti(i),function(e){a(e,"",n)}),t=[t,o="center dir isindex noframes"].join(" "),r=[t,n].join(" "),Jo(ti(o),function(e){a(e,"",r)})),r=r||[t,n].join(" "),a("html","manifest","head body"),a("head","","base command link meta noscript script style title"),a("title hr noscript br"),a("base","href target"),a("link","href rel media hreflang type sizes hreflang"),a("meta","name http-equiv content charset"),a("style","media type scoped"),a("script","src async defer type charset"),a("body","onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload",r),a("address dt dd div caption","",r),a("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn","",n),a("blockquote","cite",r),a("ol","reversed start type","li"),a("ul","","li"),a("li","value",r),a("dl","","dt dd"),a("a","href target rel media hreflang type",n),a("q","cite",n),a("ins del","cite datetime",r),a("img","src sizes srcset alt usemap ismap width height"),a("iframe","src name width height",r),a("embed","src type width height"),a("object","data type typemustmatch name usemap form width height",[r,"param"].join(" ")),a("param","name value"),a("map","name",[r,"area"].join(" ")),a("area","alt coords shape href target rel media hreflang type"),a("table","border","caption colgroup thead tfoot tbody tr"+("html4"===e?" col":"")),a("colgroup","span","col"),a("col","span"),a("tbody thead tfoot","","tr"),a("tr","","td th"),a("td","colspan rowspan headers",r),a("th","colspan rowspan headers scope abbr",r),a("form","accept-charset action autocomplete enctype method name novalidate target",r),a("fieldset","disabled form name",[r,"legend"].join(" ")),a("label","form for",n),a("input","accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"),a("button","disabled form formaction formenctype formmethod formnovalidate formtarget name type value","html4"===e?r:n),a("select","disabled form multiple name required size","option optgroup"),a("optgroup","disabled label","option"),a("option","disabled label selected value"),a("textarea","cols dirname disabled form maxlength name readonly required rows wrap"),a("menu","type label",[r,"li"].join(" ")),a("noscript","",r),"html4"!==e&&(a("wbr"),a("ruby","",[n,"rt rp"].join(" ")),a("figcaption","",r),a("mark rt rp summary bdi","",n),a("canvas","width height",r),a("video","src crossorigin poster preload autoplay mediagroup loop muted controls width height buffered",[r,"track source"].join(" ")),a("audio","src crossorigin preload autoplay mediagroup loop muted controls buffered volume",[r,"track source"].join(" ")),a("picture","","img source"),a("source","src srcset type media sizes"),a("track","kind src srclang label default"),a("datalist","",[n,"option"].join(" ")),a("article section nav aside header footer","",r),a("hgroup","","h1 h2 h3 h4 h5 h6"),a("figure","",[r,"figcaption"].join(" ")),a("time","datetime",n),a("dialog","open",r),a("command","type label icon disabled checked radiogroup command"),a("output","for form name",n),a("progress","value max",n),a("meter","value min max low high optimum",n),a("details","open",[r,"summary"].join(" ")),a("keygen","autofocus challenge disabled form keytype name")),"html5-strict"!==e&&(c("script","language xml:space"),c("style","xml:space"),c("object","declare classid code codebase codetype archive standby align border hspace vspace"),c("embed","align name hspace vspace"),c("param","valuetype type"),c("a","charset name rev shape coords"),c("br","clear"),c("applet","codebase archive code object alt name width height align hspace vspace"),c("img","name longdesc align border hspace vspace"),c("iframe","longdesc frameborder marginwidth marginheight scrolling align"),c("font basefont","size color face"),c("input","usemap align"),c("select","onchange"),c("textarea"),c("h1 h2 h3 h4 h5 h6 div p legend caption","align"),c("ul","type compact"),c("li","type"),c("ol dl menu dir","compact"),c("pre","width xml:space"),c("hr","align noshade size width"),c("isindex","prompt"),c("table","summary width frame rules cellspacing cellpadding align bgcolor"),c("col","width align char charoff valign"),c("colgroup","width align char charoff valign"),c("thead","align char charoff valign"),c("tr","align char charoff valign bgcolor"),c("th","axis align char charoff valign nowrap bgcolor width height"),c("form","accept"),c("td","abbr axis scope align char charoff valign nowrap bgcolor width height"),c("tfoot","align char charoff valign"),c("tbody","align char charoff valign"),c("area","nohref"),c("body","background bgcolor text link vlink alink")),"html4"!==e&&(c("input button select textarea","autofocus"),c("input textarea","placeholder"),c("a","download"),c("link script img","crossorigin"),c("iframe","sandbox seamless allowfullscreen")),Jo(ti("a form meter progress dfn"),function(e){s[e]&&delete s[e].children[e]}),delete s.caption.children.table,delete s.script,Xo[e]=s)},ri=function(e,n){var r;return e&&(r={},"string"==typeof e&&(e={"*":e}),Jo(e,function(e,t){r[t]=r[t.toUpperCase()]="map"===n?Go(e,/[, ]/):Zo(e,/[, ]/)})),r};function oi(i){var e,t,n,r,o,a,u,s,c,l,f,d,m,N={},p={},E=[],g={},h={},v=function(e,t,n){var r=i[e];return r?r=Go(r,/[, ]/,Go(r.toUpperCase(),/[, ]/)):(r=Xo[e])||(r=Go(t," ",Go(t.toUpperCase()," ")),r=Qo(r,n),Xo[e]=r),r};n=ni((i=i||{}).schema),!1===i.verify_html&&(i.valid_elements="*[*]"),e=ri(i.valid_styles),t=ri(i.invalid_styles,"map"),s=ri(i.valid_classes,"map"),r=v("whitespace_elements","pre script noscript style textarea video audio iframe object code"),o=v("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr"),a=v("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr track"),u=v("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls"),l=v("non_empty_elements","td th iframe video audio object script pre code",a),f=v("move_caret_before_on_enter_elements","table",l),d=v("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure"),c=v("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex option datalist select optgroup figcaption details summary",d),m=v("text_inline_elements","span strong b em i font strike u var cite dfn code mark q sup sub samp"),Jo((i.special||"script noscript noframes noembed title style textarea xmp").split(" "),function(e){h[e]=new RegExp("</"+e+"[^>]*>","gi")});var S=function(e){return new RegExp("^"+e.replace(/([?+*])/g,".$1")+"$")},y=function(e){var t,n,r,o,i,a,u,s,c,l,f,d,m,p,g,h,v,y,b,C=/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)\])?$/,x=/^([!\-])?(\w+[\\:]:\w+|[^=:<]+)?(?:([=:<])(.*))?$/,w=/[*?+]/;if(e)for(e=ti(e,","),N["@"]&&(h=N["@"].attributes,v=N["@"].attributesOrder),t=0,n=e.length;t<n;t++)if(i=C.exec(e[t])){if(p=i[1],c=i[2],g=i[3],s=i[5],a={attributes:d={},attributesOrder:m=[]},"#"===p&&(a.paddEmpty=!0),"-"===p&&(a.removeEmpty=!0),"!"===i[4]&&(a.removeEmptyAttrs=!0),h){for(y in h)d[y]=h[y];m.push.apply(m,v)}if(s)for(r=0,o=(s=ti(s,"|")).length;r<o;r++)if(i=x.exec(s[r])){if(u={},f=i[1],l=i[2].replace(/[\\:]:/g,":"),p=i[3],b=i[4],"!"===f&&(a.attributesRequired=a.attributesRequired||[],a.attributesRequired.push(l),u.required=!0),"-"===f){delete d[l],m.splice(ei(m,l),1);continue}p&&("="===p&&(a.attributesDefault=a.attributesDefault||[],a.attributesDefault.push({name:l,value:b}),u.defaultValue=b),":"===p&&(a.attributesForced=a.attributesForced||[],a.attributesForced.push({name:l,value:b}),u.forcedValue=b),"<"===p&&(u.validValues=Go(b,"?"))),w.test(l)?(a.attributePatterns=a.attributePatterns||[],u.pattern=S(l),a.attributePatterns.push(u)):(d[l]||m.push(l),d[l]=u)}h||"@"!==c||(h=d,v=m),g&&(a.outputName=c,N[g]=a),w.test(c)?(a.pattern=S(c),E.push(a)):N[c]=a}},b=function(e){N={},E=[],y(e),Jo(n,function(e,t){p[t]=e.children})},C=function(e){var a=/^(~)?(.+)$/;e&&(Xo.text_block_elements=Xo.block_elements=null,Jo(ti(e,","),function(e){var t=a.exec(e),n="~"===t[1],r=n?"span":"div",o=t[2];if(p[o]=p[r],g[o]=r,n||(c[o.toUpperCase()]={},c[o]={}),!N[o]){var i=N[r];delete(i=Qo({},i)).removeEmptyAttrs,delete i.removeEmpty,N[o]=i}Jo(p,function(e,t){e[r]&&(p[t]=e=Qo({},p[t]),e[o]=e[r])})}))},x=function(e){var o=/^([+\-]?)(\w+)\[([^\]]+)\]$/;Xo[i.schema]=null,e&&Jo(ti(e,","),function(e){var t,n,r=o.exec(e);r&&(n=r[1],t=n?p[r[2]]:p[r[2]]={"#comment":{}},t=p[r[2]],Jo(ti(r[3],"|"),function(e){"-"===n?delete t[e]:t[e]={}}))})},w=function(e){var t,n=N[e];if(n)return n;for(t=E.length;t--;)if((n=E[t]).pattern.test(e))return n};return i.valid_elements?b(i.valid_elements):(Jo(n,function(e,t){N[t]={attributes:e.attributes,attributesOrder:e.attributesOrder},p[t]=e.children}),"html5"!==i.schema&&Jo(ti("strong/b em/i"),function(e){e=ti(e,"/"),N[e[1]].outputName=e[0]}),Jo(ti("ol ul sub sup blockquote span font a table tbody tr strong em b i"),function(e){N[e]&&(N[e].removeEmpty=!0)}),Jo(ti("p h1 h2 h3 h4 h5 h6 th td pre div address caption li"),function(e){N[e].paddEmpty=!0}),Jo(ti("span"),function(e){N[e].removeEmptyAttrs=!0})),C(i.custom_elements),x(i.valid_children),y(i.extended_valid_elements),x("+ol[ul|ol],+ul[ul|ol]"),Jo({dd:"dl",dt:"dl",li:"ul ol",td:"tr",th:"tr",tr:"tbody thead tfoot",tbody:"table",thead:"table",tfoot:"table",legend:"fieldset",area:"map",param:"video audio object"},function(e,t){N[t]&&(N[t].parentsRequired=ti(e))}),i.invalid_elements&&Jo(Zo(i.invalid_elements),function(e){N[e]&&delete N[e]}),w("span")||y("span[!data-mce-type|*]"),{children:p,elements:N,getValidStyles:function(){return e},getValidClasses:function(){return s},getBlockElements:function(){return c},getInvalidStyles:function(){return t},getShortEndedElements:function(){return a},getTextBlockElements:function(){return d},getTextInlineElements:function(){return m},getBoolAttrs:function(){return u},getElementRule:w,getSelfClosingElements:function(){return o},getNonEmptyElements:function(){return l},getMoveCaretBeforeOnEnterElements:function(){return f},getWhiteSpaceElements:function(){return r},getSpecialElements:function(){return h},isValidChild:function(e,t){var n=p[e.toLowerCase()];return!(!n||!n[t.toLowerCase()])},isValid:function(e,t){var n,r,o=w(e);if(o){if(!t)return!0;if(o.attributes[t])return!0;if(n=o.attributePatterns)for(r=n.length;r--;)if(n[r].pattern.test(e))return!0}return!1},getCustomElements:function(){return g},addValidElements:y,setValidElements:b,addCustomElements:C,addValidChildren:x}}var ii=function(e,t,n,r){var o=function(e){return 1<(e=parseInt(e,10).toString(16)).length?e:"0"+e};return"#"+o(t)+o(n)+o(r)};function ai(b,e){var C,t,c,l,x=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,w=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,N=/\s*([^:]+):\s*([^;]+);?/g,E=/\s+$/,S={},k="\ufeff";for(b=b||{},e&&(c=e.getValidStyles(),l=e.getInvalidStyles()),t=("\\\" \\' \\; \\: ; : "+k).split(" "),C=0;C<t.length;C++)S[t[C]]=k+C,S[k+C]=t[C];return{toHex:function(e){return e.replace(x,ii)},parse:function(e){var t,n,r,o,i,a,u,s,c={},l=b.url_converter,f=b.url_converter_scope||this,d=function(e,t,n){var r,o,i,a;if((r=c[e+"-top"+t])&&(o=c[e+"-right"+t])&&(i=c[e+"-bottom"+t])&&(a=c[e+"-left"+t])){var u=[r,o,i,a];for(C=u.length-1;C--&&u[C]===u[C+1];);-1<C&&n||(c[e+t]=-1===C?u[0]:u.join(" "),delete c[e+"-top"+t],delete c[e+"-right"+t],delete c[e+"-bottom"+t],delete c[e+"-left"+t])}},m=function(e){var t,n=c[e];if(n){for(t=(n=n.split(" ")).length;t--;)if(n[t]!==n[0])return!1;return c[e]=n[0],!0}},p=function(e){return o=!0,S[e]},g=function(e,t){return o&&(e=e.replace(/\uFEFF[0-9]/g,function(e){return S[e]})),t||(e=e.replace(/\\([\'\";:])/g,"$1")),e},h=function(e){return String.fromCharCode(parseInt(e.slice(1),16))},v=function(e){return e.replace(/\\[0-9a-f]+/gi,h)},y=function(e,t,n,r,o,i){if(o=o||i)return"'"+(o=g(o)).replace(/\'/g,"\\'")+"'";if(t=g(t||n||r),!b.allow_script_urls){var a=t.replace(/[\s\r\n]+/g,"");if(/(java|vb)script:/i.test(a))return"";if(!b.allow_svg_data_urls&&/^data:image\/svg/i.test(a))return""}return l&&(t=l.call(f,t,"style")),"url('"+t.replace(/\'/g,"\\'")+"')"};if(e){for(e=(e=e.replace(/[\u0000-\u001F]/g,"")).replace(/\\[\"\';:\uFEFF]/g,p).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(e){return e.replace(/[;:]/g,p)});t=N.exec(e);)if(N.lastIndex=t.index+t[0].length,n=t[1].replace(E,"").toLowerCase(),r=t[2].replace(E,""),n&&r){if(n=v(n),r=v(r),-1!==n.indexOf(k)||-1!==n.indexOf('"'))continue;if(!b.allow_script_urls&&("behavior"===n||/expression\s*\(|\/\*|\*\//.test(r)))continue;"font-weight"===n&&"700"===r?r="bold":"color"!==n&&"background-color"!==n||(r=r.toLowerCase()),r=(r=r.replace(x,ii)).replace(w,y),c[n]=o?g(r,!0):r}d("border","",!0),d("border","-width"),d("border","-color"),d("border","-style"),d("padding",""),d("margin",""),i="border",u="border-style",s="border-color",m(a="border-width")&&m(u)&&m(s)&&(c[i]=c[a]+" "+c[u]+" "+c[s],delete c[a],delete c[u],delete c[s]),"medium none"===c.border&&delete c.border,"none"===c["border-image"]&&delete c["border-image"]}return c},serialize:function(i,e){var t,n,r,o,a,u="",s=function(e){var t,n,r,o;if(t=c[e])for(n=0,r=t.length;n<r;n++)e=t[n],(o=i[e])&&(u+=(0<u.length?" ":"")+e+": "+o+";")};if(e&&c)s("*"),s(e);else for(t in i)!(n=i[t])||l&&(r=t,o=e,a=void 0,(a=l["*"])&&a[r]||(a=l[o])&&a[r])||(u+=(0<u.length?" ":"")+t+": "+n+";");return u}}}var ui,si=It.each,ci=It.grep,li=ve.ie,fi=/^([a-z0-9],?)+$/i,di=/^[ \t\r\n]*$/,mi=function(n,r,o){var e={},i=r.keep_values,t={set:function(e,t,n){r.url_converter&&(t=r.url_converter.call(r.url_converter_scope||o(),t,n,e[0])),e.attr("data-mce-"+n,t).attr(n,t)},get:function(e,t){return e.attr("data-mce-"+t)||e.attr(t)}};return e={style:{set:function(e,t){null===t||"object"!=typeof t?(i&&e.attr("data-mce-style",t),e.attr("style",t)):e.css(t)},get:function(e){var t=e.attr("data-mce-style")||e.attr("style");return t=n.serialize(n.parse(t),e[0].nodeName)}}},i&&(e.href=e.src=t),e},pi=function(e,t){var n=t.attr("style"),r=e.serialize(e.parse(n),t[0].nodeName);r||(r=null),t.attr("data-mce-style",r)},gi=function(e,t){var n,r,o=0;if(e)for(n=e.nodeType,e=e.previousSibling;e;e=e.previousSibling)r=e.nodeType,(!t||3!==r||r!==n&&e.nodeValue.length)&&(o++,n=r);return o};function hi(a,u){var s,c=this;void 0===u&&(u={});var r={},i=window,o={},t=0,e=function(m,e){var p,g=0,h={};p=(e=e||{}).maxLoadTime||5e3;var v=function(e){m.getElementsByTagName("head")[0].appendChild(e)},n=function(e,t,n){var o,r,i,a,u=function(){for(var e=a.passed,t=e.length;t--;)e[t]();a.status=2,a.passed=[],a.failed=[]},s=function(){for(var e=a.failed,t=e.length;t--;)e[t]();a.status=3,a.passed=[],a.failed=[]},c=function(e,t){e()||((new Date).getTime()-i<p?we.setTimeout(t):s())},l=function(){c(function(){for(var e,t,n=m.styleSheets,r=n.length;r--;)if((t=(e=n[r]).ownerNode?e.ownerNode:e.owningElement)&&t.id===o.id)return u(),!0},l)},f=function(){c(function(){try{var e=r.sheet.cssRules;return u(),!!e}catch(t){}},f)};if(e=It._addCacheSuffix(e),h[e]?a=h[e]:(a={passed:[],failed:[]},h[e]=a),t&&a.passed.push(t),n&&a.failed.push(n),1!==a.status)if(2!==a.status)if(3!==a.status){if(a.status=1,(o=m.createElement("link")).rel="stylesheet",o.type="text/css",o.id="u"+g++,o.async=!1,o.defer=!1,i=(new Date).getTime(),"onload"in o&&!((d=navigator.userAgent.match(/WebKit\/(\d*)/))&&parseInt(d[1],10)<536))o.onload=l,o.onerror=s;else{if(0<navigator.userAgent.indexOf("Firefox"))return(r=m.createElement("style")).textContent='@import "'+e+'"',f(),void v(r);l()}var d;v(o),o.href=e}else s();else u()},t=function(t){return Zr.nu(function(e){n(t,V.compose(e,V.constant(io.value(t))),V.compose(e,V.constant(io.error(t))))})},o=function(e){return e.fold(V.identity,V.identity)};return{load:n,loadAll:function(e,n,r){no.par(H.map(e,t)).get(function(e){var t=H.partition(e,function(e){return e.isValue()});0<t.fail.length?r(t.fail.map(o)):n(t.pass.map(o))})}}}(a),l=[],f=u.schema?u.schema:oi({}),d=ai({url_converter:u.url_converter,url_converter_scope:u.url_converter_scope},u.schema),m=u.ownEvents?new Be(u.proxy):Be.Event,n=f.getBlockElements(),p=tn.overrideDefaults(function(){return{context:a,element:q.getRoot()}}),g=function(e){if(e&&a&&"string"==typeof e){var t=a.getElementById(e);return t&&t.id!==e?a.getElementsByName(e)[1]:t}return e},h=function(e){return"string"==typeof e&&(e=g(e)),p(e)},v=function(e,t,n){var r,o,i=h(e);return i.length&&(o=(r=s[t])&&r.get?r.get(i,t):i.attr(t)),void 0===o&&(o=n||""),o},y=function(e){var t=g(e);return t?t.attributes:[]},b=function(e,t,n){var r,o;""===n&&(n=null);var i=h(e);r=i.attr(t),i.length&&((o=s[t])&&o.set?o.set(i,n,t):i.attr(t,n),r!==n&&u.onSetAttrib&&u.onSetAttrib({attrElm:i,attrName:t,attrValue:n}))},C=function(){return u.root_element||a.body},x=function(e,t){return Xr.getPos(a.body,g(e),t)},w=function(e,t,n){var r=h(e);return n?r.css(t):("float"===(t=t.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}))&&(t=ve.ie&&ve.ie<12?"styleFloat":"cssFloat"),r[0]&&r[0].style?r[0].style[t]:undefined)},N=function(e){var t,n;return e=g(e),t=w(e,"width"),n=w(e,"height"),-1===t.indexOf("px")&&(t=0),-1===n.indexOf("px")&&(n=0),{w:parseInt(t,10)||e.offsetWidth||e.clientWidth,h:parseInt(n,10)||e.offsetHeight||e.clientHeight}},E=function(e,t){var n;if(!e)return!1;if(!Array.isArray(e)){if("*"===t)return 1===e.nodeType;if(fi.test(t)){var r=t.toLowerCase().split(/,/),o=e.nodeName.toLowerCase();for(n=r.length-1;0<=n;n--)if(r[n]===o)return!0;return!1}if(e.nodeType&&1!==e.nodeType)return!1}var i=Array.isArray(e)?e:[e];return 0<mt(t,i[0].ownerDocument||i[0],null,i).length},S=function(e,t,n,r){var o,i=[],a=g(e);for(r=r===undefined,n=n||("BODY"!==C().nodeName?C().parentNode:null),It.is(t,"string")&&(t="*"===(o=t)?function(e){return 1===e.nodeType}:function(e){return E(e,o)});a&&a!==n&&a.nodeType&&9!==a.nodeType;){if(!t||"function"==typeof t&&t(a)){if(!r)return[a];i.push(a)}a=a.parentNode}return r?i:null},k=function(e,t,n){var r=t;if(e)for("string"==typeof t&&(r=function(e){return E(e,t)}),e=e[n];e;e=e[n])if("function"==typeof r&&r(e))return e;return null},T=function(e,n,r){var o,t="string"==typeof e?g(e):e;if(!t)return!1;if(It.isArray(t)&&(t.length||0===t.length))return o=[],si(t,function(e,t){e&&("string"==typeof e&&(e=g(e)),o.push(n.call(r,e,t)))}),o;var i=r||c;return n.call(i,t)},A=function(e,t){h(e).each(function(e,n){si(t,function(e,t){b(n,t,e)})})},R=function(e,r){var t=h(e);li?t.each(function(e,t){if(!1!==t.canHaveHTML){for(;t.firstChild;)t.removeChild(t.firstChild);try{t.innerHTML="<br>"+r,t.removeChild(t.firstChild)}catch(n){tn("<div></div>").html("<br>"+r).contents().slice(1).appendTo(t)}return r}}):t.html(r)},_=function(e,n,r,o,i){return T(e,function(e){var t="string"==typeof n?a.createElement(n):n;return A(t,r),o&&("string"!=typeof o&&o.nodeType?t.appendChild(o):"string"==typeof o&&R(t,o)),i?t:e.appendChild(t)})},B=function(e,t,n){return _(a.createElement(e),e,t,n,!0)},D=Ko.decode,O=Ko.encodeAllRaw,P=function(e,t){var n=h(e);return t?n.each(function(){for(var e;e=this.firstChild;)3===e.nodeType&&0===e.data.length?this.removeChild(e):this.parentNode.insertBefore(e,this)}).remove():n.remove(),1<n.length?n.toArray():n[0]},L=function(e,t,n){h(e).toggleClass(t,n).each(function(){""===this.className&&tn(this).attr("class",null)})},I=function(t,e,n){return T(e,function(e){return It.is(e,"array")&&(t=t.cloneNode(!0)),n&&si(ci(e.childNodes),function(e){t.appendChild(e)}),e.parentNode.replaceChild(t,e)})},M=function(){return a.createRange()},F=function(e,t,n,r){if(It.isArray(e)){for(var o=e.length;o--;)e[o]=F(e[o],t,n,r);return e}return!u.collect||e!==a&&e!==i||l.push([e,t,n,r]),m.bind(e,t,n,r||q)},z=function(e,t,n){var r;if(It.isArray(e)){for(r=e.length;r--;)e[r]=z(e[r],t,n);return e}if(l&&(e===a||e===i))for(r=l.length;r--;){var o=l[r];e!==o[0]||t&&t!==o[1]||n&&n!==o[2]||m.unbind(o[0],o[1],o[2])}return m.unbind(e,t,n)},U=function(e){if(e&&Oo.isElement(e)){var t=e.getAttribute("data-mce-contenteditable");return t&&"inherit"!==t?t:"inherit"!==e.contentEditable?e.contentEditable:null}return null},q={doc:a,settings:u,win:i,files:o,stdMode:!0,boxModel:!0,styleSheetLoader:e,boundEvents:l,styles:d,schema:f,events:m,isBlock:function(e){if("string"==typeof e)return!!n[e];if(e){var t=e.nodeType;if(t)return!(1!==t||!n[e.nodeName])}return!1},$:p,$$:h,root:null,clone:function(t,e){if(!li||1!==t.nodeType||e)return t.cloneNode(e);if(!e){var n=a.createElement(t.nodeName);return si(y(t),function(e){b(n,e.nodeName,v(t,e.nodeName))}),n}return null},getRoot:C,getViewPort:function(e){var t=e||i,n=t.document,r=n.documentElement;return{x:t.pageXOffset||r.scrollLeft,y:t.pageYOffset||r.scrollTop,w:t.innerWidth||r.clientWidth,h:t.innerHeight||r.clientHeight}},getRect:function(e){var t,n;return e=g(e),t=x(e),n=N(e),{x:t.x,y:t.y,w:n.w,h:n.h}},getSize:N,getParent:function(e,t,n){var r=S(e,t,n,!1);return r&&0<r.length?r[0]:null},getParents:S,get:g,getNext:function(e,t){return k(e,t,"nextSibling")},getPrev:function(e,t){return k(e,t,"previousSibling")},select:function(e,t){return mt(e,g(t)||u.root_element||a,[])},is:E,add:_,create:B,createHTML:function(e,t,n){var r,o="";for(r in o+="<"+e,t)t.hasOwnProperty(r)&&null!==t[r]&&"undefined"!=typeof t[r]&&(o+=" "+r+'="'+O(t[r])+'"');return void 0!==n?o+">"+n+"</"+e+">":o+" />"},createFragment:function(e){var t,n=a.createElement("div"),r=a.createDocumentFragment();for(e&&(n.innerHTML=e);t=n.firstChild;)r.appendChild(t);return r},remove:P,setStyle:function(e,t,n){var r=h(e).css(t,n);u.update_styles&&pi(d,r)},getStyle:w,setStyles:function(e,t){var n=h(e).css(t);u.update_styles&&pi(d,n)},removeAllAttribs:function(e){return T(e,function(e){var t,n=e.attributes;for(t=n.length-1;0<=t;t--)e.removeAttributeNode(n.item(t))})},setAttrib:b,setAttribs:A,getAttrib:v,getPos:x,parseStyle:function(e){return d.parse(e)},serializeStyle:function(e,t){return d.serialize(e,t)},addStyle:function(e){var t,n;if(q!==hi.DOM&&a===document){if(r[e])return;r[e]=!0}(n=a.getElementById("mceDefaultStyles"))||((n=a.createElement("style")).id="mceDefaultStyles",n.type="text/css",(t=a.getElementsByTagName("head")[0]).firstChild?t.insertBefore(n,t.firstChild):t.appendChild(n)),n.styleSheet?n.styleSheet.cssText+=e:n.appendChild(a.createTextNode(e))},loadCSS:function(e){var n;q===hi.DOM||a!==document?(e||(e=""),n=a.getElementsByTagName("head")[0],si(e.split(","),function(e){var t;e=It._addCacheSuffix(e),o[e]||(o[e]=!0,t=B("link",{rel:"stylesheet",href:e}),n.appendChild(t))})):hi.DOM.loadCSS(e)},addClass:function(e,t){h(e).addClass(t)},removeClass:function(e,t){L(e,t,!1)},hasClass:function(e,t){return h(e).hasClass(t)},toggleClass:L,show:function(e){h(e).show()},hide:function(e){h(e).hide()},isHidden:function(e){return"none"===h(e).css("display")},uniqueId:function(e){return(e||"mce_")+t++},setHTML:R,getOuterHTML:function(e){var t="string"==typeof e?g(e):e;return Oo.isElement(t)?t.outerHTML:tn("<div></div>").append(tn(t).clone()).html()},setOuterHTML:function(e,t){h(e).each(function(){try{if("outerHTML"in this)return void(this.outerHTML=t)}catch(e){}P(tn(this).html(t),!0)})},decode:D,encode:O,insertAfter:function(e,t){var r=g(t);return T(e,function(e){var t,n;return t=r.parentNode,(n=r.nextSibling)?t.insertBefore(e,n):t.appendChild(e),e})},replace:I,rename:function(t,e){var n;return t.nodeName!==e.toUpperCase()&&(n=B(e),si(y(t),function(e){b(n,e.nodeName,v(t,e.nodeName))}),I(n,t,!0)),n||t},findCommonAncestor:function(e,t){for(var n,r=e;r;){for(n=t;n&&r!==n;)n=n.parentNode;if(r===n)break;r=r.parentNode}return!r&&e.ownerDocument?e.ownerDocument.documentElement:r},toHex:function(e){return d.toHex(It.trim(e))},run:T,getAttribs:y,isEmpty:function(e,t){var n,r,o,i,a,u,s=0;if(e=e.firstChild){a=new ao(e,e.parentNode),t=t||(f?f.getNonEmptyElements():null),i=f?f.getWhiteSpaceElements():{};do{if(o=e.nodeType,Oo.isElement(e)){var c=e.getAttribute("data-mce-bogus");if(c){e=a.next("all"===c);continue}if(u=e.nodeName.toLowerCase(),t&&t[u]){if("br"===u){s++,e=a.next();continue}return!1}for(n=(r=y(e)).length;n--;)if("name"===(u=r[n].nodeName)||"data-mce-bookmark"===u)return!1}if(8===o)return!1;if(3===o&&!di.test(e.nodeValue))return!1;if(3===o&&e.parentNode&&i[e.parentNode.nodeName]&&di.test(e.nodeValue))return!1;e=a.next()}while(e)}return s<=1},createRng:M,nodeIndex:gi,split:function(e,t,n){var r,o,i,a=M();if(e&&t)return a.setStart(e.parentNode,gi(e)),a.setEnd(t.parentNode,gi(t)),r=a.extractContents(),(a=M()).setStart(t.parentNode,gi(t)+1),a.setEnd(e.parentNode,gi(e)+1),o=a.extractContents(),(i=e.parentNode).insertBefore(Io.trimNode(q,r),e),n?i.insertBefore(n,e):i.insertBefore(t,e),i.insertBefore(Io.trimNode(q,o),e),P(e),n||t},bind:F,unbind:z,fire:function(e,t,n){return m.fire(e,t,n)},getContentEditable:U,getContentEditableParent:function(e){for(var t=C(),n=null;e&&e!==t&&null===(n=U(e));e=e.parentNode);return n},destroy:function(){if(l)for(var e=l.length;e--;){var t=l[e];m.unbind(t[0],t[1],t[2])}mt.setDocument&&mt.setDocument()},isChildOf:function(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1},dumpRng:function(e){return"startContainer: "+e.startContainer.nodeName+", startOffset: "+e.startOffset+", endContainer: "+e.endContainer.nodeName+", endOffset: "+e.endOffset}};return s=mi(d,u,function(){return q}),q}(ui=hi||(hi={})).DOM=ui(document),ui.nodeIndex=gi;var vi=hi,yi=vi.DOM,bi=It.each,Ci=It.grep,xi=function(e){return"function"==typeof e},wi=function(){var f={},o=[],i={},a=[],d=0;this.isDone=function(e){return 2===f[e]},this.markDone=function(e){f[e]=2},this.add=this.load=function(e,t,n,r){f[e]===undefined&&(o.push(e),f[e]=0),t&&(i[e]||(i[e]=[]),i[e].push({success:t,failure:r,scope:n||this}))},this.remove=function(e){delete f[e],delete i[e]},this.loadQueue=function(e,t,n){this.loadScripts(o,e,t,n)},this.loadScripts=function(n,e,t,r){var s,c=[],l=function(t,e){bi(i[e],function(e){xi(e[t])&&e[t].call(e.scope)}),i[e]=undefined};a.push({success:e,failure:r,scope:t||this}),(s=function(){var e=Ci(n);if(n.length=0,bi(e,function(e){var t,n,r,o,i,a,u;2!==f[e]?3!==f[e]?1!==f[e]&&(f[e]=1,d++,t=e,n=function(){f[e]=2,d--,l("success",e),s()},r=function(){f[e]=3,d--,c.push(e),l("failure",e),s()},u=function(){a.remove(i),o&&(o.onreadystatechange=o.onload=o=null),n()},i=(a=yi).uniqueId(),(o=document.createElement("script")).id=i,o.type="text/javascript",o.src=It._addCacheSuffix(t),"onreadystatechange"in o?o.onreadystatechange=function(){/loaded|complete/.test(o.readyState)&&u()}:o.onload=u,o.onerror=function(){xi(r)?r():"undefined"!=typeof console&&console.log&&console.log("Failed to load script: "+t)},(document.getElementsByTagName("head")[0]||document.body).appendChild(o)):l("failure",e):l("success",e)}),!d){var t=a.slice(0);a.length=0,bi(t,function(e){0===c.length?xi(e.success)&&e.success.call(e.scope):xi(e.failure)&&e.failure.call(e.scope,c)})}})()}};wi.ScriptLoader=new wi;var Ni,Ei=It.each;function Si(){var r=this,o=[],a={},u={},i=[],s=function(e){var t;return u[e]&&(t=u[e].dependencies),t||[]},c=function(e,t){return"object"==typeof t?t:"string"==typeof e?{prefix:"",resource:t,suffix:""}:{prefix:e.prefix,resource:t,suffix:e.suffix}},l=function(n,e,t){var r=s(name);Ei(r,function(e){var t=c(n,e);f(t.resource,t,undefined,undefined)}),e&&(t?e.call(t):e.call(wi))},f=function(e,t,n,r,o){if(!a[e]){var i="string"==typeof t?t:t.prefix+t.resource+t.suffix;0!==i.indexOf("/")&&-1===i.indexOf("://")&&(i=Si.baseURL+"/"+i),a[e]=i.substring(0,i.lastIndexOf("/")),u[e]?l(t,n,r):wi.ScriptLoader.add(i,function(){return l(t,n,r)},r,o)}};return{items:o,urls:a,lookup:u,_listeners:i,get:function(e){return u[e]?u[e].instance:undefined},dependencies:s,requireLangPack:function(e,t){var n=Si.language;if(n&&!1!==Si.languageLoad){if(t)if(-1!==(t=","+t+",").indexOf(","+n.substr(0,2)+","))n=n.substr(0,2);else if(-1===t.indexOf(","+n+","))return;wi.ScriptLoader.add(a[e]+"/langs/"+n+".js")}},add:function(t,e,n){o.push(e),u[t]={instance:e,dependencies:n};var r=H.partition(i,function(e){return e.name===t});return i=r.fail,Ei(r.pass,function(e){e.callback()}),e},remove:function(e){delete a[e],delete u[e]},createUrl:c,addComponents:function(e,t){var n=r.urls[e];Ei(t,function(e){wi.ScriptLoader.add(n+"/"+e)})},load:f,waitFor:function(e,t){u.hasOwnProperty(e)?t():i.push({name:e,callback:t})}}}(Ni=Si||(Si={})).PluginManager=Ni(),Ni.ThemeManager=Ni();var ki,Ti="\ufeff",Ai=function(e){return e===Ti},Ri=Ti,_i=function(e){return e.replace(new RegExp(Ti,"g"),"")},Bi=Oo.isElement,Di=Oo.isText,Oi=function(e){return Di(e)&&(e=e.parentNode),Bi(e)&&e.hasAttribute("data-mce-caret")},Pi=function(e){return Di(e)&&Ai(e.data)},Li=function(e){return Oi(e)||Pi(e)},Ii=function(e){return e.firstChild!==e.lastChild||!Oo.isBr(e.firstChild)},Mi=function(e){var t=e.container();return e&&Oo.isText(t)&&t.data.charAt(e.offset())===Ri},Fi=function(e){var t=e.container();return e&&Oo.isText(t)&&t.data.charAt(e.offset()-1)===Ri},zi=function(e,t,n){var r,o,i;return(r=t.ownerDocument.createElement(e)).setAttribute("data-mce-caret",n?"before":"after"),r.setAttribute("data-mce-bogus","all"),r.appendChild(((i=document.createElement("br")).setAttribute("data-mce-bogus","1"),i)),o=t.parentNode,n?o.insertBefore(r,t):t.nextSibling?o.insertBefore(r,t.nextSibling):o.appendChild(r),r},Ui=function(e){return Di(e)&&e.data[0]===Ri},qi=function(e){return Di(e)&&e.data[e.data.length-1]===Ri},Vi=function(e){return e&&e.hasAttribute("data-mce-caret")?(t=e.getElementsByTagName("br"),n=t[t.length-1],Oo.isBogus(n)&&n.parentNode.removeChild(n),e.removeAttribute("data-mce-caret"),e.removeAttribute("data-mce-bogus"),e.removeAttribute("style"),e.removeAttribute("_moz_abspos"),e):null;var t,n},Hi=Oo.isContentEditableTrue,ji=Oo.isContentEditableFalse,$i=Oo.isBr,Wi=Oo.isText,Ki=Oo.matchNodeNames("script style textarea"),Xi=Oo.matchNodeNames("img input textarea hr iframe video audio object"),Yi=Oo.matchNodeNames("table"),Gi=Li,Ji=function(e){return!Gi(e)&&(Wi(e)?!Ki(e.parentNode):Xi(e)||$i(e)||Yi(e)||Qi(e))},Qi=function(e){return!1===(t=e,Oo.isElement(t)&&"true"===t.getAttribute("unselectable"))&&ji(e);var t},Zi=function(e,t){return Ji(e)&&function(e,t){for(e=e.parentNode;e&&e!==t;e=e.parentNode){if(Qi(e))return!1;if(Hi(e))return!0}return!0}(e,t)},ea=Math.round,ta=function(e){return e?{left:ea(e.left),top:ea(e.top),bottom:ea(e.bottom),right:ea(e.right),width:ea(e.width),height:ea(e.height)}:{left:0,top:0,bottom:0,right:0,width:0,height:0}},na=function(e,t){return e=ta(e),t||(e.left=e.left+e.width),e.right=e.left,e.width=0,e},ra=function(e,t,n){return 0<=e&&e<=Math.min(t.height,n.height)/2},oa=function(e,t){return e.bottom-e.height/2<t.top||!(e.top>t.bottom)&&ra(t.top-e.bottom,e,t)},ia=function(e,t){return e.top>t.bottom||!(e.bottom<t.top)&&ra(t.bottom-e.top,e,t)},aa=function(e){var t=e.startContainer,n=e.startOffset;return t.hasChildNodes()&&e.endOffset===n+1?t.childNodes[n]:null},ua=function(e,t){return 1===e.nodeType&&e.hasChildNodes()&&(t>=e.childNodes.length&&(t=e.childNodes.length-1),e=e.childNodes[t]),e},sa=new RegExp("[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62-\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62-\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1abe\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20dd-\u20e0\u20e1\u20e2-\u20e4\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\ua670-\ua672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]"),ca=function(e){return"string"==typeof e&&768<=e.charCodeAt(0)&&sa.test(e)},la=[].slice,fa=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r=la.call(arguments);return r.length-1>=e.length?e.apply(this,r.slice(1)):function(){var e=r.concat([].slice.call(arguments));return fa.apply(this,e)}},da={constant:function(e){return function(){return e}},negate:function(t){return function(e){return!t(e)}},and:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=la.call(arguments);return function(e){for(var t=0;t<n.length;t++)if(!n[t](e))return!1;return!0}},or:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=la.call(arguments);return function(e){for(var t=0;t<n.length;t++)if(n[t](e))return!0;return!1}},curry:fa,compose:function(t,n){return function(e){return t(n(e))}},noop:function(){}},ma=function(e,t){for(var n=[],r=0;r<e.length;r++){var o=e[r];if(!o.isSome())return A.none();n.push(o.getOrDie())}return A.some(t.apply(null,n))},pa=Oo.isElement,ga=Ji,ha=Oo.matchStyleValues("display","block table"),va=Oo.matchStyleValues("float","left right"),ya=da.and(pa,ga,da.negate(va)),ba=da.negate(Oo.matchStyleValues("white-space","pre pre-line pre-wrap")),Ca=Oo.isText,xa=Oo.isBr,wa=vi.nodeIndex,Na=ua,Ea=function(e){return"createRange"in e?e.createRange():vi.DOM.createRng()},Sa=function(e){return e&&/[\r\n\t ]/.test(e)},ka=function(e){return!!e.setStart&&!!e.setEnd},Ta=function(e){var t,n=e.startContainer,r=e.startOffset;return!!(Sa(e.toString())&&ba(n.parentNode)&&Oo.isText(n)&&(t=n.data,Sa(t[r-1])||Sa(t[r+1])))},Aa=function(e){return 0===e.left&&0===e.right&&0===e.top&&0===e.bottom},Ra=function(e){var t,n,r,o,i,a,u,s;return t=0<(n=e.getClientRects()).length?ta(n[0]):ta(e.getBoundingClientRect()),!ka(e)&&xa(e)&&Aa(t)?(i=(r=e).ownerDocument,a=Ea(i),u=i.createTextNode("\xa0"),(s=r.parentNode).insertBefore(u,r),a.setStart(u,0),a.setEnd(u,1),o=ta(a.getBoundingClientRect()),s.removeChild(u),o):Aa(t)&&ka(e)?function(e){var t=e.startContainer,n=e.endContainer,r=e.startOffset,o=e.endOffset;if(t===n&&Oo.isText(n)&&0===r&&1===o){var i=e.cloneRange();return i.setEndAfter(n),Ra(i)}return null}(e):t},_a=function(e,t){var n=na(e,t);return n.width=1,n.right=n.left+1,n},Ba=function(e){var t,n,r=[],o=function(e){var t,n;0!==e.height&&(0<r.length&&(t=e,n=r[r.length-1],t.left===n.left&&t.top===n.top&&t.bottom===n.bottom&&t.right===n.right)||r.push(e))},i=function(e,t){var n=Ea(e.ownerDocument);if(t<e.data.length){if(ca(e.data[t]))return r;if(ca(e.data[t-1])&&(n.setStart(e,t),n.setEnd(e,t+1),!Ta(n)))return o(_a(Ra(n),!1)),r}0<t&&(n.setStart(e,t-1),n.setEnd(e,t),Ta(n)||o(_a(Ra(n),!1))),t<e.data.length&&(n.setStart(e,t),n.setEnd(e,t+1),Ta(n)||o(_a(Ra(n),!0)))};if(Ca(e.container()))return i(e.container(),e.offset()),r;if(pa(e.container()))if(e.isAtEnd())n=Na(e.container(),e.offset()),Ca(n)&&i(n,n.data.length),ya(n)&&!xa(n)&&o(_a(Ra(n),!1));else{if(n=Na(e.container(),e.offset()),Ca(n)&&i(n,0),ya(n)&&e.isAtEnd())return o(_a(Ra(n),!1)),r;t=Na(e.container(),e.offset()-1),ya(t)&&!xa(t)&&(ha(t)||ha(n)||!ya(n))&&o(_a(Ra(t),!1)),ya(n)&&o(_a(Ra(n),!0))}return r};function Da(t,n,e){var r=function(){return e||(e=Ba(Da(t,n))),e};return{container:da.constant(t),offset:da.constant(n),toRange:function(){var e;return(e=Ea(t.ownerDocument)).setStart(t,n),e.setEnd(t,n),e},getClientRects:r,isVisible:function(){return 0<r().length},isAtStart:function(){return Ca(t),0===n},isAtEnd:function(){return Ca(t)?n>=t.data.length:n>=t.childNodes.length},isEqual:function(e){return e&&t===e.container()&&n===e.offset()},getNode:function(e){return Na(t,e?n-1:n)}}}(ki=Da||(Da={})).fromRangeStart=function(e){return ki(e.startContainer,e.startOffset)},ki.fromRangeEnd=function(e){return ki(e.endContainer,e.endOffset)},ki.after=function(e){return ki(e.parentNode,wa(e)+1)},ki.before=function(e){return ki(e.parentNode,wa(e))},ki.isAbove=function(e,t){return ma([H.head(t.getClientRects()),H.last(e.getClientRects())],oa).getOr(!1)},ki.isBelow=function(e,t){return ma([H.last(t.getClientRects()),H.head(e.getClientRects())],ia).getOr(!1)},ki.isAtStart=function(e){return!!e&&e.isAtStart()},ki.isAtEnd=function(e){return!!e&&e.isAtEnd()},ki.isTextPosition=function(e){return!!e&&Oo.isText(e.container())},ki.isElementPosition=function(e){return!1===ki.isTextPosition(e)};var Oa,Pa,La=Da,Ia=Oo.isElement,Ma=Oo.isText,Fa=function(e){var t=e.parentNode;t&&t.removeChild(e)},za=function(e,t){0===t.length?Fa(e):e.nodeValue=t},Ua=function(e){var t=_i(e);return{count:e.length-t.length,text:t}},qa=function(e,t){return ja(e),t},Va=function(e,t){return Ma(e)&&t.container()===e?(r=t,o=Ua((n=e).data.substr(0,r.offset())),i=Ua(n.data.substr(r.offset())),0<(a=o.text+i.text).length?(za(n,a),La(n,r.offset()-o.count)):r):qa(e,t);var n,r,o,i,a},Ha=function(e,t){return t.container()===e.parentNode?(n=e,o=(r=t).container(),i=H.indexOf(H.from(o.childNodes),n).map(function(e){return e<r.offset()?La(o,r.offset()-1):r}).getOr(r),ja(n),i):qa(e,t);var n,r,o,i},ja=function(e){if(Ia(e)&&Li(e)&&(Ii(e)?e.removeAttribute("data-mce-caret"):Fa(e)),Ma(e)){var t=_i(function(e){try{return e.nodeValue}catch(t){return""}}(e));za(e,t)}},$a={removeAndReposition:function(e,t){return La.isTextPosition(t)?Va(e,t):Ha(e,t)},remove:ja},Wa=function(e){return La.isTextPosition(e)?0===e.offset():Ji(e.getNode())},Ka=function(e){if(La.isTextPosition(e)){var t=e.container();return e.offset()===t.data.length}return Ji(e.getNode(!0))},Xa=function(e,t){return!La.isTextPosition(e)&&!La.isTextPosition(t)&&e.getNode()===t.getNode(!0)},Ya=function(e,t,n){return e?!Xa(t,n)&&(r=t,!(!La.isTextPosition(r)&&Oo.isBr(r.getNode())))&&Ka(t)&&Wa(n):!Xa(n,t)&&Wa(t)&&Ka(n);var r},Ga=function(e,t,n){var r=Ys(t);return A.from(e?r.next(n):r.prev(n))},Ja=function(e,t){var n,r,o,i,a,u=e?t.firstChild:t.lastChild;return Oo.isText(u)?A.some(La(u,e?0:u.data.length)):u?Ji(u)?A.some(e?La.before(u):(a=u,Oo.isBr(a)?La.before(a):La.after(a))):(r=t,o=u,i=(n=e)?La.before(o):La.after(o),Ga(n,r,i)):A.none()},Qa={fromPosition:Ga,nextPosition:V.curry(Ga,!0),prevPosition:V.curry(Ga,!1),navigate:function(t,n,r){return Ga(t,n,r).bind(function(e){return bs(r,e,n)&&Ya(t,r,e)?Ga(t,n,e):A.some(e)})},positionIn:Ja,firstPositionIn:V.curry(Ja,!0),lastPositionIn:V.curry(Ja,!1)},Za=Oo.isContentEditableTrue,eu=Oo.isContentEditableFalse,tu=function(e,t,n,r,o){return t._selectionOverrides.showCaret(e,n,r,o)},nu=function(e,t){var n,r;return e.fire("BeforeObjectSelected",{target:t}).isDefaultPrevented()?null:((r=(n=t).ownerDocument.createRange()).selectNode(n),r)},ru=function(e,t,n){var r=Ss(1,e.getBody(),t),o=La.fromRangeStart(r),i=o.getNode();if(eu(i))return tu(1,e,i,!o.isAtEnd(),!1);var a=o.getNode(!0);if(eu(a))return tu(1,e,a,!1,!1);var u=e.dom.getParent(o.getNode(),function(e){return eu(e)||Za(e)});return eu(u)?tu(1,e,u,!1,n):null},ou=function(e,t,n){if(!t||!t.collapsed)return t;var r=ru(e,t,n);return r||t};(Pa=Oa||(Oa={}))[Pa.Br=0]="Br",Pa[Pa.Block=1]="Block",Pa[Pa.Wrap=2]="Wrap",Pa[Pa.Eol=3]="Eol";var iu,au,uu=function(e,t){return e===iu.Backwards?t.reverse():t},su=function(e,t,n,r){for(var o,i,a,u,s,c,l=Ys(n),f=r,d=[];f&&(s=l,c=f,o=t===iu.Forwards?s.next(c):s.prev(c));){if(Oo.isBr(o.getNode(!1)))return t===iu.Forwards?{positions:uu(t,d).concat([o]),breakType:Oa.Br,breakAt:A.some(o)}:{positions:uu(t,d),breakType:Oa.Br,breakAt:A.some(o)};if(o.isVisible()){if(e(f,o)){var m=(i=t,a=f,u=o,Oo.isBr(u.getNode(i===iu.Forwards))?Oa.Br:!1===bs(a,u)?Oa.Block:Oa.Wrap);return{positions:uu(t,d),breakType:m,breakAt:A.some(o)}}d.push(o),f=o}else f=o}return{positions:uu(t,d),breakType:Oa.Eol,breakAt:A.none()}},cu=function(n,r,o,e){return r(o,e).breakAt.map(function(e){var t=r(o,e).positions;return n===iu.Backwards?t.concat(e):[e].concat(t)}).getOr([])},lu=function(e,i){return H.foldl(e,function(e,o){return e.fold(function(){return A.some(o)},function(r){return ma([H.head(r.getClientRects()),H.head(o.getClientRects())],function(e,t){var n=Math.abs(i-e.left);return Math.abs(i-t.left)<=n?o:r}).or(e)})},A.none())},fu=function(t,e){return H.head(e.getClientRects()).bind(function(e){return lu(t,e.left)})},du=V.curry(su,Da.isAbove,-1),mu=V.curry(su,Da.isBelow,1),pu=V.curry(cu,-1,du),gu=V.curry(cu,1,mu),hu=function(e,t){return Pr.all(t,e)},vu=function(e,t,n,r,o){var i,a,u,s,c,l=hu(Vn.fromDom(n),"td,th").map(function(e){return e.dom()}),f=H.filter((i=e,a=l,H.bind(a,function(e){var t,n,r=(t=e.getBoundingClientRect(),n=-1,{left:t.left-n,top:t.top-n,right:t.right+2*n,bottom:t.bottom+2*n,width:t.width+n,height:t.height+n});return[{x:r.left,y:i(r),cell:e},{x:r.right,y:i(r),cell:e}]})),function(e){return t(e,o)});return(u=f,s=r,c=o,H.foldl(u,function(e,r){return e.fold(function(){return A.some(r)},function(e){var t=Math.sqrt(Math.abs(e.x-s)+Math.abs(e.y-c)),n=Math.sqrt(Math.abs(r.x-s)+Math.abs(r.y-c));return A.some(n<t?r:e)})},A.none())).map(function(e){return e.cell})},yu=V.curry(vu,function(e){return e.bottom},function(e,t){return e.y<t}),bu=V.curry(vu,function(e){return e.top},function(e,t){return e.y>t}),Cu=function(t,n){return H.head(n.getClientRects()).bind(function(e){return yu(t,e.left,e.top)}).bind(function(e){return fu((t=e,Qa.lastPositionIn(t).map(function(e){return du(t,e).positions.concat(e)}).getOr([])),n);var t})},xu=function(t,n){return H.last(n.getClientRects()).bind(function(e){return bu(t,e.left,e.top)}).bind(function(e){return fu((t=e,Qa.firstPositionIn(t).map(function(e){return[e].concat(mu(t,e).positions)}).getOr([])),n);var t})},wu=function(e){for(var t=0,n=0,r=e;r&&r.nodeType;)t+=r.offsetLeft||0,n+=r.offsetTop||0,r=r.offsetParent;return{x:t,y:n}},Nu=function(e,t,n){var r,o,i,a,u,s=e.dom,c=s.getRoot(),l=0;if(u={elm:t,alignToTop:n},e.fire("scrollIntoView",u),!u.isDefaultPrevented()&&Oo.isElement(t)){if(!1===n&&(l=t.offsetHeight),"BODY"!==c.nodeName){var f=e.selection.getScrollContainer();if(f)return r=wu(t).y-wu(f).y+l,a=f.clientHeight,void((r<(i=f.scrollTop)||i+a<r+25)&&(f.scrollTop=r<i?r:r-a+25))}o=s.getViewPort(e.getWin()),r=s.getPos(t).y+l,i=o.y,a=o.h,(r<o.y||i+a<r+25)&&e.getWin().scrollTo(0,r<i?r:r-a+25)}},Eu=function(d,e){H.head(Da.fromRangeStart(e).getClientRects()).each(function(e){var t,n,r,o,i,a,u,s,c,l=function(e){if(e.inline)return e.getBody().getBoundingClientRect();var t=e.getWin();return{left:0,right:t.innerWidth,top:0,bottom:t.innerHeight,width:t.innerWidth,height:t.innerHeight}}(d),f={x:(i=t=l,a=n=e,a.left>i.left&&a.right<i.right?0:a.left<i.left?a.left-i.left:a.right-i.right),y:(r=t,o=n,o.top>r.top&&o.bottom<r.bottom?0:o.top<r.top?o.top-r.top:o.bottom-r.bottom)};s=0!==f.x?0<f.x?f.x+4:f.x-4:0,c=0!==f.y?0<f.y?f.y+4:f.y-4:0,(u=d).inline?(u.getBody().scrollLeft+=s,u.getBody().scrollTop+=c):u.getWin().scrollBy(s,c)})},Su=function(e,t,n){var r=e.getParam(t,n);if(-1!==r.indexOf("=")){var o=e.getParam(t,"","hash");return o.hasOwnProperty(e.id)?o[e.id]:n}return r},ku=function(e){return e.getParam("iframe_attrs",{})},Tu=function(e){return e.getParam("doctype","<!DOCTYPE html>")},Au=function(e){return e.getParam("document_base_url","")},Ru=function(e){return Su(e,"body_id","tinymce")},_u=function(e){return Su(e,"body_class","")},Bu=function(e){return e.getParam("content_security_policy","")},Du=function(e){return e.getParam("br_in_pre",!0)},Ou=function(e){if(e.getParam("force_p_newlines",!1))return"p";var t=e.getParam("forced_root_block","p");return!1===t?"":t},Pu=function(e){return e.getParam("forced_root_block_attrs",{})},Lu=function(e){return e.getParam("br_newline_selector",".mce-toc h2,figcaption,caption")},Iu=function(e){return e.getParam("no_newline_selector","")},Mu=function(e){return e.getParam("keep_styles",!0)},Fu=function(e){return e.getParam("end_container_on_empty_block",!1)},zu=function(e){return It.explode(e.getParam("font_size_style_values",""))},Uu=function(e){return It.explode(e.getParam("font_size_classes",""))},qu=function(t,n){$r.parent(t).each(function(e){e.dom().insertBefore(n.dom(),t.dom())})},Vu=function(e,t){e.dom().appendChild(t.dom())},Hu={before:qu,after:function(e,t){$r.nextSibling(e).fold(function(){$r.parent(e).each(function(e){Vu(e,t)})},function(e){qu(e,t)})},prepend:function(t,n){$r.firstChild(t).fold(function(){Vu(t,n)},function(e){t.dom().insertBefore(n.dom(),e.dom())})},append:Vu,appendAt:function(e,t,n){$r.child(e,n).fold(function(){Vu(e,t)},function(e){qu(e,t)})},wrap:function(e,t){qu(e,t),Vu(t,e)}},ju=Un.detect().browser,$u=function(){return ju.isIE()||ju.isEdge()||ju.isFirefox()},Wu=function(e,t){e.selection.setRng(t),Eu(e,t)},Ku=function(t,n,e){var r=t(n,e);return r.breakType===Oa.Wrap&&0===r.positions.length?r.breakAt.map(function(e){return t(n,e).breakAt.isNone()}).getOr(!0):r.breakAt.isNone()},Xu=da.curry(Ku,du),Yu=da.curry(Ku,mu),Gu=function(e,t,n,r){var o,i,a,u,s=e.selection.getRng(),c=t?1:-1;if($u()&&(o=t,i=s,a=n,u=La.fromRangeStart(i),Qa.positionIn(!o,a).map(function(e){return e.isEqual(u)}).getOr(!1))){var l=tu(c,e,n,!t,!0);return Wu(e,l),!0}return!1},Ju=function(e,t){var n=t.getNode(e);return Oo.isElement(n)&&"TABLE"===n.nodeName?A.some(n):A.none()},Qu=function(u,s,c){var e=Ju(!!s,c),t=!1===s;e.fold(function(){return Wu(u,c.toRange())},function(a){return Qa.positionIn(t,u.getBody()).filter(function(e){return e.isEqual(c)}).fold(function(){return Wu(u,c.toRange())},function(e){return n=s,o=a,t=c,void((i=Ou(r=u))?r.undoManager.transact(function(){var e=Vn.fromTag(i);lr.setAll(e,Pu(r)),Hu.append(e,Vn.fromTag("br")),n?Hu.after(Vn.fromDom(o),e):Hu.before(Vn.fromDom(o),e);var t=r.dom.createRng();t.setStart(e.dom(),0),t.setEnd(e.dom(),0),Wu(r,t)}):Wu(r,t.toRange()));var n,r,o,t,i})})},Zu=function(e,t,n,r){var o,i,a,u,s,c,l=e.selection.getRng(),f=La.fromRangeStart(l),d=e.getBody();if(!t&&Xu(r,f)){var m=(u=d,Cu(s=n,c=f).orThunk(function(){return H.head(c.getClientRects()).bind(function(e){return lu(pu(u,La.before(s)),e.left)})}).getOr(La.before(s)));return Qu(e,t,m),!0}return!(!t||!Yu(r,f))&&(o=d,m=xu(i=n,a=f).orThunk(function(){return H.head(a.getClientRects()).bind(function(e){return lu(gu(o,La.after(i)),e.left)})}).getOr(La.after(i)),Qu(e,t,m),!0)},es=function(t,n){return function(){return A.from(t.dom.getParent(t.selection.getNode(),"td,th")).bind(function(e){return A.from(t.dom.getParent(e,"table")).map(function(e){return Gu(t,n,e)})}).getOr(!1)}},ts=function(n,r){return function(){return A.from(n.dom.getParent(n.selection.getNode(),"td,th")).bind(function(t){return A.from(n.dom.getParent(t,"table")).map(function(e){return Zu(n,r,e,t)})}).getOr(!1)}},ns=function(e){var t=e,n=function(){return t};return{get:n,set:function(e){t=e},clone:function(){return ns(n())}}},rs=Oo.isContentEditableFalse,os=function(e,t,n){var r,o,i,a,u,s=na(t.getBoundingClientRect(),n);return"BODY"===e.tagName?(r=e.ownerDocument.documentElement,o=e.scrollLeft||r.scrollLeft,i=e.scrollTop||r.scrollTop):(u=e.getBoundingClientRect(),o=e.scrollLeft-u.left,i=e.scrollTop-u.top),s.left+=o,s.right+=o,s.top+=i,s.bottom+=i,s.width=1,0<(a=t.offsetWidth-t.clientWidth)&&(n&&(a*=-1),s.left+=a,s.right+=a),s},is=function(a,u,e){var t,s,c=ns(A.none()),l=function(){!function(e){var t,n,r,o,i;for(t=tn("*[contentEditable=false]",e),o=0;o<t.length;o++)r=(n=t[o]).previousSibling,qi(r)&&(1===(i=r.data).length?r.parentNode.removeChild(r):r.deleteData(i.length-1,1)),r=n.nextSibling,Ui(r)&&(1===(i=r.data).length?r.parentNode.removeChild(r):r.deleteData(0,1))}(a),s&&($a.remove(s),s=null),c.get().each(function(e){tn(e.caret).remove(),c.set(A.none())}),clearInterval(t)},f=function(){t=we.setInterval(function(){e()?tn("div.mce-visual-caret",a).toggleClass("mce-visual-caret-hidden"):tn("div.mce-visual-caret",a).addClass("mce-visual-caret-hidden")},500)};return{show:function(t,e){var n,r,o;if(l(),o=e,Oo.isElement(o)&&/^(TD|TH)$/i.test(o.tagName))return null;if(!u(e))return s=function(e,t){var n,r,o;if(r=e.ownerDocument.createTextNode(Ri),o=e.parentNode,t){if(n=e.previousSibling,Di(n)){if(Li(n))return n;if(qi(n))return n.splitText(n.data.length-1)}o.insertBefore(r,e)}else{if(n=e.nextSibling,Di(n)){if(Li(n))return n;if(Ui(n))return n.splitText(1),n}e.nextSibling?o.insertBefore(r,e.nextSibling):o.appendChild(r)}return r}(e,t),r=e.ownerDocument.createRange(),rs(s.nextSibling)?(r.setStart(s,0),r.setEnd(s,0)):(r.setStart(s,1),r.setEnd(s,1)),r;s=zi("p",e,t),n=os(a,e,t),tn(s).css("top",n.top);var i=tn('<div class="mce-visual-caret" data-mce-bogus="all"></div>').css(n).appendTo(a)[0];return c.set(A.some({caret:i,element:e,before:t})),c.get().each(function(e){t&&tn(e.caret).addClass("mce-visual-caret-before")}),f(),(r=e.ownerDocument.createRange()).setStart(s,0),r.setEnd(s,0),r},hide:l,getCss:function(){return".mce-visual-caret {position: absolute;background-color: black;background-color: currentcolor;}.mce-visual-caret-hidden {display: none;}*[data-mce-caret] {position: absolute;left: -1000px;right: auto;top: 0;margin: 0;padding: 0;}"},reposition:function(){c.get().each(function(e){var t=os(a,e.element,e.before);tn(e.caret).css(t)})},destroy:function(){return we.clearInterval(t)}}},as=function(e){return rs(e)||Oo.isTable(e)&&$u()},us=Oo.isContentEditableFalse,ss=Oo.matchStyleValues("display","block table table-cell table-caption list-item"),cs=Li,ls=Oi,fs=da.curry,ds=Oo.isElement,ms=Ji,ps=function(e){return 0<e},gs=function(e){return e<0},hs=function(e,t){for(var n;n=e(t);)if(!ls(n))return n;return null},vs=function(e,t,n,r,o){var i=new ao(e,r);if(gs(t)){if((us(e)||ls(e))&&n(e=hs(i.prev,!0)))return e;for(;e=hs(i.prev,o);)if(n(e))return e}if(ps(t)){if((us(e)||ls(e))&&n(e=hs(i.next,!0)))return e;for(;e=hs(i.next,o);)if(n(e))return e}return null},ys=function(e,t){for(;e&&e!==t;){if(ss(e))return e;e=e.parentNode}return null},bs=function(e,t,n){return ys(e.container(),n)===ys(t.container(),n)},Cs=function(e,t){var n,r;return t?(n=t.container(),r=t.offset(),ds(n)?n.childNodes[r+e]:null):null},xs=function(e,t){var n=t.ownerDocument.createRange();return e?(n.setStartBefore(t),n.setEndBefore(t)):(n.setStartAfter(t),n.setEndAfter(t)),n},ws=function(e,t,n){var r,o,i,a;for(o=e?"previousSibling":"nextSibling";n&&n!==t;){if(r=n[o],cs(r)&&(r=r[o]),us(r)){if(a=n,ys(r,i=t)===ys(a,i))return r;break}if(ms(r))break;n=n.parentNode}return null},Ns=fs(xs,!0),Es=fs(xs,!1),Ss=function(e,t,n){var r,o,i,a,u=fs(ws,!0,t),s=fs(ws,!1,t);if(o=n.startContainer,i=n.startOffset,Oi(o)){if(ds(o)||(o=o.parentNode),"before"===(a=o.getAttribute("data-mce-caret"))&&(r=o.nextSibling,as(r)))return Ns(r);if("after"===a&&(r=o.previousSibling,as(r)))return Es(r)}if(!n.collapsed)return n;if(Oo.isText(o)){if(cs(o)){if(1===e){if(r=s(o))return Ns(r);if(r=u(o))return Es(r)}if(-1===e){if(r=u(o))return Es(r);if(r=s(o))return Ns(r)}return n}if(qi(o)&&i>=o.data.length-1)return 1===e&&(r=s(o))?Ns(r):n;if(Ui(o)&&i<=1)return-1===e&&(r=u(o))?Es(r):n;if(i===o.data.length)return(r=s(o))?Ns(r):n;if(0===i)return(r=u(o))?Es(r):n}return n},ks=function(e,t){var n=Cs(e,t);return us(n)&&!Oo.isBogusAll(n)},Ts=function(e,t){return Oo.isTable(Cs(e,t))},As=function(e,t){return A.from(Cs(e?0:-1,t)).filter(us)},Rs=function(e,t,n){var r=Ss(e,t,n);return-1===e?Da.fromRangeStart(r):Da.fromRangeEnd(r)},_s=fs(ks,0),Bs=fs(ks,-1),Ds=fs(Ts,0),Os=fs(Ts,-1);(au=iu||(iu={}))[au.Backwards=-1]="Backwards",au[au.Forwards=1]="Forwards";var Ps,Ls,Is,Ms,Fs,zs=Oo.isContentEditableFalse,Us=Oo.isText,qs=Oo.isElement,Vs=Oo.isBr,Hs=Ji,js=function(e){return Xi(e)||!!Qi(t=e)&&!0!==Bt.reduce(t.getElementsByTagName("*"),function(e,t){return e||Hi(t)},!1);var t},$s=Zi,Ws=function(e,t){return e.hasChildNodes()&&t<e.childNodes.length?e.childNodes[t]:null},Ks=function(e,t){if(ps(e)){if(Hs(t.previousSibling)&&!Us(t.previousSibling))return La.before(t);if(Us(t))return La(t,0)}if(gs(e)){if(Hs(t.nextSibling)&&!Us(t.nextSibling))return La.after(t);if(Us(t))return La(t,t.data.length)}return gs(e)?Vs(t)?La.before(t):La.after(t):La.before(t)},Xs=function(e,t,n){var r,o,i,a,u;if(!qs(n)||!t)return null;if(t.isEqual(La.after(n))&&n.lastChild){if(u=La.after(n.lastChild),gs(e)&&Hs(n.lastChild)&&qs(n.lastChild))return Vs(n.lastChild)?La.before(n.lastChild):u}else u=t;var s,c,l,f=u.container(),d=u.offset();if(Us(f)){if(gs(e)&&0<d)return La(f,--d);if(ps(e)&&d<f.length)return La(f,++d);r=f}else{if(gs(e)&&0<d&&(o=Ws(f,d-1),Hs(o)))return!js(o)&&(i=vs(o,e,$s,o))?Us(i)?La(i,i.data.length):La.after(i):Us(o)?La(o,o.data.length):La.before(o);if(ps(e)&&d<f.childNodes.length&&(o=Ws(f,d),Hs(o)))return Vs(o)&&n.lastChild===o?null:(s=o,c=n,Oo.isBr(s)&&(l=Xs(1,La.after(s),c))&&!bs(La.before(s),La.before(l),c)?Xs(e,La.after(o),n):!js(o)&&(i=vs(o,e,$s,o))?Us(i)?La(i,0):La.before(i):Us(o)?La(o,0):La.after(o));r=o||u.getNode()}return(ps(e)&&u.isAtEnd()||gs(e)&&u.isAtStart())&&(r=vs(r,e,da.constant(!0),n,!0),$s(r,n))?Ks(e,r):(o=vs(r,e,$s,n),!(a=Bt.last(Bt.filter(function(e,t){for(var n=[];e&&e!==t;)n.push(e),e=e.parentNode;return n}(f,n),zs)))||o&&a.contains(o)?o?Ks(e,o):null:u=ps(e)?La.after(a):La.before(a))},Ys=function(t){return{next:function(e){return Xs(iu.Forwards,e,t)},prev:function(e){return Xs(iu.Backwards,e,t)}}},Gs=function(e){return It.grep(e.childNodes,function(e){return"LI"===e.nodeName})},Js=function(e){return e&&e.firstChild&&e.firstChild===e.lastChild&&("\xa0"===(t=e.firstChild).data||Oo.isBr(t));var t},Qs=function(e){return 0<e.length&&(!(t=e[e.length-1]).firstChild||Js(t))?e.slice(0,-1):e;var t},Zs=function(e,t){var n=e.getParent(t,e.isBlock);return n&&"LI"===n.nodeName?n:null},ec=function(e,t){var n=La.after(e),r=Ys(t).prev(n);return r?r.toRange():null},tc=function(t,e,n){var r,o,i,a,u=t.parentNode;return It.each(e,function(e){u.insertBefore(e,t)}),r=t,o=n,i=La.before(r),(a=Ys(o).next(i))?a.toRange():null},nc=function(e,t){var n,r,o,i,a,u,s=t.firstChild,c=t.lastChild;return s&&"meta"===s.name&&(s=s.next),c&&"mce_marker"===c.attr("id")&&(c=c.prev),r=c,u=(n=e).getNonEmptyElements(),r&&(r.isEmpty(u)||(o=r,n.getBlockElements()[o.name]&&(a=o).firstChild&&a.firstChild===a.lastChild&&("br"===(i=o.firstChild).name||"\xa0"===i.value)))&&(c=c.prev),!(!s||s!==c||"ul"!==s.name&&"ol"!==s.name)},rc=function(e,o,i,t){var n,r,a,u,s,c,l,f,d,m,p,g,h,v,y,b,C,x,w,N=(n=o,r=t,c=e.serialize(r),l=n.createFragment(c),u=(a=l).firstChild,s=a.lastChild,u&&"META"===u.nodeName&&u.parentNode.removeChild(u),s&&"mce_marker"===s.id&&s.parentNode.removeChild(s),a),E=Zs(o,i.startContainer),S=Qs(Gs(N.firstChild)),k=o.getRoot(),T=function(e){var t=La.fromRangeStart(i),n=Ys(o.getRoot()),r=1===e?n.prev(t):n.next(t);return!r||Zs(o,r.getNode())!==E};return T(1)?tc(E,S,k):T(2)?(f=E,d=S,m=k,o.insertAfter(d.reverse(),f),ec(d[0],m)):(g=S,h=k,v=p=E,b=(y=i).cloneRange(),C=y.cloneRange(),b.setStartBefore(v),C.setEndAfter(v),x=[b.cloneContents(),C.cloneContents()],(w=p.parentNode).insertBefore(x[0],p),It.each(g,function(e){w.insertBefore(e,p)}),w.insertBefore(x[1],p),w.removeChild(p),ec(g[g.length-1],h))},oc=function(e,t){return!!Zs(e,t)},ic=Oo.isText,ac=Oo.isBogus,uc=vi.nodeIndex,sc=function(e){var t=e.parentNode;return ac(t)?sc(t):t},cc=function(e){return e?Bt.reduce(e.childNodes,function(e,t){return ac(t)&&"BR"!==t.nodeName?e=e.concat(cc(t)):e.push(t),e},[]):[]},lc=function(t){return function(e){return t===e}},fc=function(e){var t,r,n,o;return(ic(e)?"text()":e.nodeName.toLowerCase())+"["+(r=cc(sc(t=e)),n=Bt.findIndex(r,lc(t),t),r=r.slice(0,n+1),o=Bt.reduce(r,function(e,t,n){return ic(t)&&ic(r[n-1])&&e++,e},0),r=Bt.filter(r,Oo.matchNodeNames(t.nodeName)),(n=Bt.findIndex(r,lc(t),t))-o)+"]"},dc=function(e,t){var n,r,o,i,a,u=[];return n=t.container(),r=t.offset(),ic(n)?o=function(e,t){for(;(e=e.previousSibling)&&ic(e);)t+=e.data.length;return t}(n,r):(r>=(i=n.childNodes).length?(o="after",r=i.length-1):o="before",n=i[r]),u.push(fc(n)),a=function(e,t,n){var r=[];for(t=t.parentNode;!(t===e||n&&n(t));t=t.parentNode)r.push(t);return r}(e,n),a=Bt.filter(a,da.negate(Oo.isBogus)),(u=u.concat(Bt.map(a,function(e){return fc(e)}))).reverse().join("/")+","+o},mc=function(e,t){var n,r,o;return t?(t=(n=t.split(","))[0].split("/"),o=1<n.length?n[1]:"before",(r=Bt.reduce(t,function(e,t){return(t=/([\w\-\(\)]+)\[([0-9]+)\]/.exec(t))?("text()"===t[1]&&(t[1]="#text"),n=e,r=t[1],o=parseInt(t[2],10),i=cc(n),i=Bt.filter(i,function(e,t){return!ic(e)||!ic(i[t-1])}),(i=Bt.filter(i,Oo.matchNodeNames(r)))[o]):null;var n,r,o,i},e))?ic(r)?function(e,t){for(var n,r=e,o=0;ic(r);){if(n=r.data.length,o<=t&&t<=o+n){e=r,t-=o;break}if(!ic(r.nextSibling)){e=r,t=n;break}o+=n,r=r.nextSibling}return ic(e)&&t>e.data.length&&(t=e.data.length),La(e,t)}(r,parseInt(o,10)):(o="after"===o?uc(r)+1:uc(r),La(r.parentNode,o)):null):null},pc=Oo.isContentEditableFalse,gc=function(e,t,n,r,o){var i,a=r[o?"startContainer":"endContainer"],u=r[o?"startOffset":"endOffset"],s=[],c=0,l=e.getRoot();for(Oo.isText(a)?s.push(n?function(e,t,n){var r,o;for(o=e(t.data.slice(0,n)).length,r=t.previousSibling;r&&Oo.isText(r);r=r.previousSibling)o+=e(r.data).length;return o}(t,a,u):u):(u>=(i=a.childNodes).length&&i.length&&(c=1,u=Math.max(0,i.length-1)),s.push(e.nodeIndex(i[u],n)+c));a&&a!==l;a=a.parentNode)s.push(e.nodeIndex(a,n));return s},hc=function(e){Oo.isText(e)&&0===e.data.length&&e.parentNode.removeChild(e)},vc=function(e,t,n){var r=0;return It.each(e.select(t),function(e){if("all"!==e.getAttribute("data-mce-bogus"))return e!==n&&void r++}),r},yc=function(e,t){var n,r,o,i=t?"start":"end";n=e[i+"Container"],r=e[i+"Offset"],Oo.isElement(n)&&"TR"===n.nodeName&&(n=(o=n.childNodes)[Math.min(t?r:r-1,o.length-1)])&&(r=t?0:n.childNodes.length,e["set"+(t?"Start":"End")](n,r))},bc=function(e){return yc(e,!0),yc(e,!1),e},Cc=function(e,t){var n;if(Oo.isElement(e)&&(e=ua(e,t),pc(e)))return e;if(Li(e)){if(Oo.isText(e)&&Oi(e)&&(e=e.parentNode),n=e.previousSibling,pc(n))return n;if(n=e.nextSibling,pc(n))return n}},xc=function(e,t,n){var r=n.getNode(),o=r?r.nodeName:null,i=n.getRng();if(pc(r)||"IMG"===o)return{name:o,index:vc(n.dom,o,r)};var a,u,s,c,l,f,d,m=Cc((a=i).startContainer,a.startOffset)||Cc(a.endContainer,a.endOffset);return m?{name:o=m.tagName,index:vc(n.dom,o,m)}:(u=e,c=t,l=i,f=(s=n).dom,(d={}).start=gc(f,u,c,l,!0),s.isCollapsed()||(d.end=gc(f,u,c,l,!1)),d)},wc=function(e,t,n){var r={"data-mce-type":"bookmark",id:t,style:"overflow:hidden;line-height:0px"};return n?e.create("span",r,""):e.create("span",r)},Nc=function(e,t){var n=e.dom,r=e.getRng(),o=n.uniqueId(),i=e.isCollapsed(),a=e.getNode(),u=a.nodeName;if("IMG"===u)return{name:u,index:vc(n,u,a)};var s=bc(r.cloneRange());if(!i){s.collapse(!1);var c=wc(n,o+"_end",t);s.insertNode(c),hc(c.nextSibling)}(r=bc(r)).collapse(!0);var l=wc(n,o+"_start",t);return r.insertNode(l),hc(l.previousSibling),e.moveToBookmark({id:o,keep:1}),{id:o}},Ec={getBookmark:function(e,t,n){return 2===t?xc(_i,n,e):3===t?(o=(r=e).getRng(),{start:dc(r.dom.getRoot(),La.fromRangeStart(o)),end:dc(r.dom.getRoot(),La.fromRangeEnd(o))}):t?{rng:e.getRng()}:Nc(e,!1);var r,o},getUndoBookmark:V.curry(xc,V.identity,!0),getPersistentBookmark:Nc},Sc="_mce_caret",kc=function(e){return Oo.isElement(e)&&e.id===Sc},Tc=function(e,t){for(;t&&t!==e;){if(t.id===Sc)return t;t=t.parentNode}return null},Ac=function(e,t){return!e.isBlock(t)||t.innerHTML||ve.ie||(t.innerHTML='<br data-mce-bogus="1" />'),t},Rc=function(e,t){return Qa.lastPositionIn(e).fold(function(){return!1},function(e){return t.setStart(e.container(),e.offset()),t.setEnd(e.container(),e.offset()),!0})},_c=function(e,t,n){return!(!1!==t.hasChildNodes()||!Tc(e,t)||(o=n,i=(r=t).ownerDocument.createTextNode(Ri),r.appendChild(i),o.setStart(i,0),o.setEnd(i,0),0));var r,o,i},Bc=function(e,t,n,r){var o,i,a,u,s=n[t?"start":"end"],c=e.getRoot();if(s){for(a=s[0],i=c,o=s.length-1;1<=o;o--){if(u=i.childNodes,_c(c,i,r))return!0;if(s[o]>u.length-1)return!!_c(c,i,r)||Rc(i,r);i=u[s[o]]}3===i.nodeType&&(a=Math.min(s[0],i.nodeValue.length)),1===i.nodeType&&(a=Math.min(s[0],i.childNodes.length)),t?r.setStart(i,a):r.setEnd(i,a)}return!0},Dc=function(e){return Oo.isText(e)&&0<e.data.length},Oc=function(e,t,n){var r,o,i,a,u,s,c=e.get(n.id+"_"+t),l=n.keep;if(c){if(r=c.parentNode,"start"===t?l?c.hasChildNodes()?(r=c.firstChild,o=1):Dc(c.nextSibling)?(r=c.nextSibling,o=0):Dc(c.previousSibling)?(r=c.previousSibling,o=c.previousSibling.data.length):(r=c.parentNode,o=e.nodeIndex(c)+1):o=e.nodeIndex(c):l?c.hasChildNodes()?(r=c.firstChild,o=1):Dc(c.previousSibling)?(r=c.previousSibling,o=c.previousSibling.data.length):(r=c.parentNode,o=e.nodeIndex(c)):o=e.nodeIndex(c),u=r,s=o,!l){for(a=c.previousSibling,i=c.nextSibling,It.each(It.grep(c.childNodes),function(e){Oo.isText(e)&&(e.nodeValue=e.nodeValue.replace(/\uFEFF/g,""))});c=e.get(n.id+"_"+t);)e.remove(c,!0);a&&i&&a.nodeType===i.nodeType&&Oo.isText(a)&&!ve.opera&&(o=a.nodeValue.length,a.appendData(i.nodeValue),e.remove(i),u=a,s=o)}return A.some(La(u,s))}return A.none()},Pc=function(e,t){var n,r,o,i,a,u,s,c,l,f,d,m,p,g,h,v,y=e.dom;if(t){if(v=t,It.isArray(v.start))return g=t,h=(p=y).createRng(),Bc(p,!0,g,h)&&Bc(p,!1,g,h)?A.some(h):A.none();if("string"==typeof t.start)return A.some((f=t,d=(l=y).createRng(),m=mc(l.getRoot(),f.start),d.setStart(m.container(),m.offset()),m=mc(l.getRoot(),f.end),d.setEnd(m.container(),m.offset()),d));if(t.hasOwnProperty("id"))return s=Oc(o=y,"start",i=t),c=Oc(o,"end",i),ma([s,(a=c,u=s,a.isSome()?a:u)],function(e,t){var n=o.createRng();return n.setStart(Ac(o,e.container()),e.offset()),n.setEnd(Ac(o,t.container()),t.offset()),n});if(t.hasOwnProperty("name"))return n=y,r=t,A.from(n.select(r.name)[r.index]).map(function(e){var t=n.createRng();return t.selectNode(e),t});if(t.hasOwnProperty("rng"))return A.some(t.rng)}return A.none()},Lc=function(e,t,n){return Ec.getBookmark(e,t,n)},Ic=function(t,e){Pc(t,e).each(function(e){t.setRng(e)})},Mc=function(e){return Oo.isElement(e)&&"SPAN"===e.tagName&&"bookmark"===e.getAttribute("data-mce-type")},Fc=It.each,zc=function(o){this.compare=function(e,t){if(e.nodeName!==t.nodeName)return!1;var n=function(n){var r={};return Fc(o.getAttribs(n),function(e){var t=e.nodeName.toLowerCase();0!==t.indexOf("_")&&"style"!==t&&0!==t.indexOf("data-")&&(r[t]=o.getAttrib(n,t))}),r},r=function(e,t){var n,r;for(r in e)if(e.hasOwnProperty(r)){if(void 0===(n=t[r]))return!1;if(e[r]!==n)return!1;delete t[r]}for(r in t)if(t.hasOwnProperty(r))return!1;return!0};return!(!r(n(e),n(t))||!r(o.parseStyle(o.getAttrib(e,"style")),o.parseStyle(o.getAttrib(t,"style")))||Mc(e)||Mc(t))}},Uc=function(t,e){H.each(e,function(e){Hu.before(t,e)})},qc=function(t,e){H.each(e,function(e){Hu.append(t,e)})},Vc=function(e){var t=e.dom();null!==t.parentNode&&t.parentNode.removeChild(t)},Hc={empty:function(e){e.dom().textContent="",H.each($r.children(e),function(e){Vc(e)})},remove:Vc,unwrap:function(e){var t=$r.children(e);0<t.length&&Uc(e,t),Vc(e)}},jc=(Ps=Zn.isText,Ls="text",Is=function(e){return Ps(e)?A.from(e.dom().nodeValue):A.none()},Ms=Un.detect().browser,{get:function(e){if(!Ps(e))throw new Error("Can only get "+Ls+" value of a "+Ls+" node");return Fs(e).getOr("")},getOption:Fs=Ms.isIE()&&10===Ms.version.major?function(e){try{return Is(e)}catch(Dw){return A.none()}}:Is,set:function(e,t){if(!Ps(e))throw new Error("Can only set raw "+Ls+" value of a "+Ls+" node");e.dom().nodeValue=t}}),$c=function(e){return jc.get(e)},Wc=function(e){var t=hu(e,"br"),n=H.filter(function(e){for(var t=[],n=e.dom();n;)t.push(Vn.fromDom(n)),n=n.lastChild;return t}(e).slice(-1),go);t.length===n.length&&H.each(n,Hc.remove)},Kc=function(e){Hc.empty(e),Hu.append(e,Vn.fromHtml('<br data-mce-bogus="1">'))},Xc=function(n){$r.lastChild(n).each(function(t){$r.prevSibling(t).each(function(e){mo(n)&&go(t)&&mo(e)&&Hc.remove(t)})})},Yc=It.makeMap;function Gc(e){var u,s,c,l,f,d=[];return u=(e=e||{}).indent,s=Yc(e.indent_before||""),c=Yc(e.indent_after||""),l=Ko.getEncodeFunc(e.entity_encoding||"raw",e.entities),f="html"===e.element_format,{start:function(e,t,n){var r,o,i,a;if(u&&s[e]&&0<d.length&&0<(a=d[d.length-1]).length&&"\n"!==a&&d.push("\n"),d.push("<",e),t)for(r=0,o=t.length;r<o;r++)i=t[r],d.push(" ",i.name,'="',l(i.value,!0),'"');d[d.length]=!n||f?">":" />",n&&u&&c[e]&&0<d.length&&0<(a=d[d.length-1]).length&&"\n"!==a&&d.push("\n")},end:function(e){var t;d.push("</",e,">"),u&&c[e]&&0<d.length&&0<(t=d[d.length-1]).length&&"\n"!==t&&d.push("\n")},text:function(e,t){0<e.length&&(d[d.length]=t?e:l(e))},cdata:function(e){d.push("<![CDATA[",e,"]]>")},comment:function(e){d.push("\x3c!--",e,"--\x3e")},pi:function(e,t){t?d.push("<?",e," ",l(t),"?>"):d.push("<?",e,"?>"),u&&d.push("\n")},doctype:function(e){d.push("<!DOCTYPE",e,">",u?"\n":"")},reset:function(){d.length=0},getContent:function(){return d.join("").replace(/\n$/,"")}}}function Jc(t,p){void 0===p&&(p=oi());var g=Gc(t);return(t=t||{}).validate=!("validate"in t)||t.validate,{serialize:function(e){var f,d;d=t.validate,f={3:function(e){g.text(e.value,e.raw)},8:function(e){g.comment(e.value)},7:function(e){g.pi(e.name,e.value)},10:function(e){g.doctype(e.value)},4:function(e){g.cdata(e.value)},11:function(e){if(e=e.firstChild)for(;m(e),e=e.next;);}},g.reset();var m=function(e){var t,n,r,o,i,a,u,s,c,l=f[e.type];if(l)l(e);else{if(t=e.name,n=e.shortEnded,r=e.attributes,d&&r&&1<r.length&&((a=[]).map={},c=p.getElementRule(e.name))){for(u=0,s=c.attributesOrder.length;u<s;u++)(o=c.attributesOrder[u])in r.map&&(i=r.map[o],a.map[o]=i,a.push({name:o,value:i}));for(u=0,s=r.length;u<s;u++)(o=r[u].name)in a.map||(i=r.map[o],a.map[o]=i,a.push({name:o,value:i}));r=a}if(g.start(e.name,r,n),!n){if(e=e.firstChild)for(;m(e),e=e.next;);g.end(t)}}};return 1!==e.type||t.inner?f[11](e):m(e),g.getContent()}}}var Qc=function(a){var u=La.fromRangeStart(a),s=La.fromRangeEnd(a),c=a.commonAncestorContainer;return Qa.fromPosition(!1,c,s).map(function(e){return!bs(u,s,c)&&bs(u,e,c)?(t=u.container(),n=u.offset(),r=e.container(),o=e.offset(),(i=document.createRange()).setStart(t,n),i.setEnd(r,o),i):a;var t,n,r,o,i}).getOr(a)},Zc=function(e){return e.collapsed?e:Qc(e)},el=Oo.matchNodeNames("td th"),tl=function(o,e,t){var n,r,i,a,u,s,c,l,f,d,m,p,g=o.schema.getTextInlineElements(),h=o.selection,v=o.dom;if(/^ | $/.test(e)&&(e=function(e){var t,n,r;t=h.getRng(),n=t.startContainer,r=t.startOffset;var o=function(e){return n[e]&&3===n[e].nodeType};return 3===n.nodeType&&(0<r?e=e.replace(/^ /," "):o("previousSibling")||(e=e.replace(/^ /," ")),r<n.length?e=e.replace(/ (<br>|)$/," "):o("nextSibling")||(e=e.replace(/( | )(<br>|)$/," "))),e}(e)),n=o.parser,p=t.merge,r=Jc({validate:o.settings.validate},o.schema),m='<span id="mce_marker" data-mce-type="bookmark">​</span>',s={content:e,format:"html",selection:!0,paste:t.paste},(s=o.fire("BeforeSetContent",s)).isDefaultPrevented())o.fire("SetContent",{content:s.content,format:"html",selection:!0,paste:t.paste});else{-1===(e=s.content).indexOf("{$caret}")&&(e+="{$caret}"),e=e.replace(/\{\$caret\}/,m);var y,b,C,x,w=(l=h.getRng()).startContainer||(l.parentElement?l.parentElement():null),N=o.getBody();w===N&&h.isCollapsed()&&v.isBlock(N.firstChild)&&(y=N.firstChild)&&!o.schema.getShortEndedElements()[y.nodeName]&&v.isEmpty(N.firstChild)&&((l=v.createRng()).setStart(N.firstChild,0),l.setEnd(N.firstChild,0),h.setRng(l)),h.isCollapsed()||(o.selection.setRng(Zc(o.selection.getRng())),o.getDoc().execCommand("Delete",!1,null),C=(b=h.getRng()).startContainer,x=b.startOffset,3===C.nodeType&&b.collapsed&&("\xa0"===C.data[x]?(C.deleteData(x,1),/[\u00a0| ]$/.test(e)||(e+=" ")):"\xa0"===C.data[x-1]&&(C.deleteData(x-1,1),/[\u00a0| ]$/.test(e)||(e=" "+e))));var E,S,k,T={context:(i=h.getNode()).nodeName.toLowerCase(),data:t.data,insert:!0};if(u=n.parse(e,T),!0===t.paste&&nc(o.schema,u)&&oc(v,i))return l=rc(r,v,o.selection.getRng(),u),o.selection.setRng(l),void o.fire("SetContent",s);if(function(e){for(var t=e;t=t.walk();)1===t.type&&t.attr("data-mce-fragment","1")}(u),"mce_marker"===(f=u.lastChild).attr("id"))for(f=(c=f).prev;f;f=f.walk(!0))if(3===f.type||!v.isBlock(f.name)){o.schema.isValidChild(f.parent.name,"span")&&f.parent.insert(c,f,"br"===f.name);break}if(o._selectionOverrides.showBlockCaretContainer(i),T.invalid){for(h.setContent(m),i=h.getNode(),a=o.getBody(),9===i.nodeType?i=f=a:f=i;f!==a;)f=(i=f).parentNode;e=i===a?a.innerHTML:v.getOuterHTML(i),e=r.serialize(n.parse(e.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i,function(){return r.serialize(u)}))),i===a?v.setHTML(a,e):v.setOuterHTML(i,e)}else e=r.serialize(u),function(e,t,n){if("all"===n.getAttribute("data-mce-bogus"))n.parentNode.insertBefore(e.dom.createFragment(t),n);else{var r=n.firstChild,o=n.lastChild;!r||r===o&&"BR"===r.nodeName?e.dom.setHTML(n,t):e.selection.setContent(t)}}(o,e,i);!function(){if(p){var n=o.getBody(),r=new zc(v);It.each(v.select("*[data-mce-fragment]"),function(e){for(var t=e.parentNode;t&&t!==n;t=t.parentNode)g[e.nodeName.toLowerCase()]&&r.compare(t,e)&&v.remove(e,!0)})}}(),function(e){var t,n,r;if(e){if(h.scrollIntoView(e),t=function(e){for(var t=o.getBody();e&&e!==t;e=e.parentNode)if("false"===o.dom.getContentEditable(e))return e;return null}(e))return v.remove(e),h.select(t);l=v.createRng(),(f=e.previousSibling)&&3===f.nodeType?(l.setStart(f,f.nodeValue.length),ve.ie||(d=e.nextSibling)&&3===d.nodeType&&(f.appendData(d.data),d.parentNode.removeChild(d))):(l.setStartBefore(e),l.setEndBefore(e)),n=v.getParent(e,v.isBlock),v.remove(e),n&&v.isEmpty(n)&&(o.$(n).empty(),l.setStart(n,0),l.setEnd(n,0),el(n)||n.getAttribute("data-mce-fragment")||!(r=function(e){var t=La.fromRangeStart(e);if(t=Ys(o.getBody()).next(t))return t.toRange()}(l))?v.add(n,v.create("br",{"data-mce-bogus":"1"})):(l=r,v.remove(n))),h.setRng(l)}}(v.get("mce_marker")),E=o.getBody(),It.each(E.getElementsByTagName("*"),function(e){e.removeAttribute("data-mce-fragment")}),S=o.dom,k=o.selection.getStart(),A.from(S.getParent(k,"td,th")).map(Vn.fromDom).each(Xc),o.fire("SetContent",s),o.addVisual()}},nl=function(e,t){var n,r,o="string"!=typeof(n=t)?(r=It.extend({paste:n.paste,data:{paste:n.paste}},n),{content:n.content,details:r}):{content:n,details:{}};tl(e,o.content,o.details)};function rl(e,t,n,r,o){return e(n,r)?A.some(n):k.isFunction(o)&&o(n)?A.none():t(n,r,o)}var ol=function(e,t,n){for(var r=e.dom(),o=k.isFunction(n)?n:V.constant(!1);r.parentNode;){r=r.parentNode;var i=Vn.fromDom(r);if(t(i))return A.some(i);if(o(i))break}return A.none()},il=function(e,t){return H.find(e.dom().childNodes,V.compose(t,Vn.fromDom)).map(Vn.fromDom)},al=function(e,r){var o=function(e){for(var t=0;t<e.childNodes.length;t++){if(r(Vn.fromDom(e.childNodes[t])))return A.some(Vn.fromDom(e.childNodes[t]));var n=o(e.childNodes[t]);if(n.isSome())return n}return A.none()};return o(e.dom())},ul={first:function(e){return al(mr.body(),e)},ancestor:ol,closest:function(e,t,n){return rl(function(e){return t(e)},ol,e,t,n)},sibling:function(t,n){var e=t.dom();return e.parentNode?il(Vn.fromDom(e.parentNode),function(e){return!Mr.eq(t,e)&&n(e)}):A.none()},child:il,descendant:al},sl=kr.immutable("sections","settings"),cl=Un.detect().deviceType.isTouch(),ll=["lists","autolink","autosave"],fl={theme:"mobile"},dl=function(e){var t=k.isArray(e)?e.join(" "):e,n=H.map(k.isString(t)?t.split(" "):[],On);return H.filter(n,function(e){return 0<e.length})},ml=function(e,t){return e.sections().hasOwnProperty(t)},pl=function(e,t,n,r){var o,i,a=dl(n.forced_plugins),u=dl(r.plugins),s=e&&ml(t,"mobile")?(o=u,H.filter(o,V.curry(H.contains,ll))):u,c=(i=s,[].concat(dl(a)).concat(dl(i)));return It.extend(r,{plugins:c.join(" ")})},gl=function(e,t,n,r){var o,i,a,u,s,c,l,f,d,m,p,g,h,v=(o=["mobile"],i=r,a=ir.bifilter(i,function(e,t){return H.contains(o,t)}),sl(a.t,a.f)),y=It.extend(t,n,v.settings(),(p=e,h=(g=v).settings().inline,p&&ml(g,"mobile")&&!h?(l="mobile",f=fl,d=v.sections(),m=d.hasOwnProperty(l)?d[l]:{},It.extend({},f,m)):{}),{validate:!0,content_editable:v.settings().inline,external_plugins:(u=n,s=v.settings(),c=s.external_plugins?s.external_plugins:{},u&&u.external_plugins?It.extend({},u.external_plugins,c):c)});return pl(e,v,n,y)},hl=function(e,t,n){return A.from(t.settings[n]).filter(e)},vl=V.curry(hl,k.isString),yl=function(e,t,n,r){var o,i,a,u=t in e.settings?e.settings[t]:n;return"hash"===r?(a={},"string"==typeof(i=u)?H.each(0<i.indexOf("=")?i.split(/[;,](?![^=;,]*(?:[;,]|$))/):i.split(","),function(e){var t=e.split("=");1<t.length?a[It.trim(t[0])]=It.trim(t[1]):a[It.trim(t[0])]=It.trim(t)}):a=i,a):"string"===r?hl(k.isString,e,t).getOr(n):"number"===r?hl(k.isNumber,e,t).getOr(n):"boolean"===r?hl(k.isBoolean,e,t).getOr(n):"object"===r?hl(k.isObject,e,t).getOr(n):"array"===r?hl(k.isArray,e,t).getOr(n):"string[]"===r?hl((o=k.isString,function(e){return k.isArray(e)&&H.forall(e,o)}),e,t).getOr(n):"function"===r?hl(k.isFunction,e,t).getOr(n):u},bl=/[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/,Cl=function(e,t){var n=t.container(),r=t.offset();return e?Pi(n)?Oo.isText(n.nextSibling)?La(n.nextSibling,0):La.after(n):Mi(t)?La(n,r+1):t:Pi(n)?Oo.isText(n.previousSibling)?La(n.previousSibling,n.previousSibling.data.length):La.before(n):Fi(t)?La(n,r-1):t},xl={isInlineTarget:function(e,t){var n=vl(e,"inline_boundaries_selector").getOr("a[href],code");return Pr.is(Vn.fromDom(t),n)},findRootInline:function(e,t,n){var r,o,i,a=(r=e,o=t,i=n,H.filter(vi.DOM.getParents(i.container(),"*",o),r));return A.from(a[a.length-1])},isRtl:function(e){return"rtl"===vi.DOM.getStyle(e,"direction",!0)||(t=e.textContent,bl.test(t));var t},isAtZwsp:function(e){return Mi(e)||Fi(e)},normalizePosition:Cl,normalizeForwards:V.curry(Cl,!0),normalizeBackwards:V.curry(Cl,!1),hasSameParentBlock:function(e,t,n){var r=ys(t,e),o=ys(n,e);return r&&r===o}},wl=function(e,t){return Mr.contains(e,t)?ul.closest(t,function(e){return ho(e)||yo(e)},(n=e,function(e){return Mr.eq(n,Vn.fromDom(e.dom().parentNode))})):A.none();var n},Nl=function(e){var t,n,r;e.dom.isEmpty(e.getBody())&&(e.setContent(""),n=(t=e).getBody(),r=n.firstChild&&t.dom.isBlock(n.firstChild)?n.firstChild:n,t.selection.setCursorLocation(r,0))},El=function(i,a,u){return ma([Qa.firstPositionIn(u),Qa.lastPositionIn(u)],function(e,t){var n=xl.normalizePosition(!0,e),r=xl.normalizePosition(!1,t),o=xl.normalizePosition(!1,a);return i?Qa.nextPosition(u,o).map(function(e){return e.isEqual(r)&&a.isEqual(n)}).getOr(!1):Qa.prevPosition(u,o).map(function(e){return e.isEqual(n)&&a.isEqual(r)}).getOr(!1)}).getOr(!0)},Sl=function(e,t,n){return ul.ancestor(e,function(e){return Pr.is(e,t)},n)},kl=Sl,Tl=function(e,t){return Pr.one(t,e)},Al=function(e,t,n){return rl(Pr.is,Sl,e,t,n)},Rl=function(e,t,n){return kl(e,t,n).isSome()},_l=function(e,t){return Oo.isText(t)&&/^[ \t\r\n]*$/.test(t.data)&&!1===(n=e,r=t,o=Vn.fromDom(n),i=Vn.fromDom(r),Rl(i,"pre,code",V.curry(Mr.eq,o)));var n,r,o,i},Bl=function(e,t){return Ji(t)&&!1===_l(e,t)||(n=t,Oo.isElement(n)&&"A"===n.nodeName&&n.hasAttribute("name"))||Dl(t);var n},Dl=Oo.hasAttribute("data-mce-bookmark"),Ol=Oo.hasAttribute("data-mce-bogus"),Pl=Oo.hasAttributeValue("data-mce-bogus","all"),Ll=function(e){return function(e){var t,n,r=0;if(Bl(e,e))return!1;if(!(n=e.firstChild))return!0;t=new ao(n,e);do{if(Pl(n))n=t.next(!0);else if(Ol(n))n=t.next();else if(Oo.isBr(n))r++,n=t.next();else{if(Bl(e,n))return!1;n=t.next()}}while(n);return r<=1}(e.dom())},Il=kr.immutable("block","position"),Ml=kr.immutable("from","to"),Fl=function(e,t){var n=Vn.fromDom(e),r=Vn.fromDom(t.container());return wl(n,r).map(function(e){return Il(e,t)})},zl=function(o,i,e){var t=Fl(o,La.fromRangeStart(e)),n=t.bind(function(e){return Qa.fromPosition(i,o,e.position()).bind(function(e){return Fl(o,e).map(function(e){return t=o,n=i,r=e,Oo.isBr(r.position().getNode())&&!1===Ll(r.block())?Qa.positionIn(!1,r.block().dom()).bind(function(e){return e.isEqual(r.position())?Qa.fromPosition(n,t,e).bind(function(e){return Fl(t,e)}):A.some(r)}).getOr(r):r;var t,n,r})})});return ma([t,n],Ml).filter(function(e){return r=e,!1===Mr.eq(r.from().block(),r.to().block())&&(n=e,$r.parent(n.from().block()).bind(function(t){return $r.parent(n.to().block()).filter(function(e){return Mr.eq(t,e)})}).isSome())&&(t=e,!1===Oo.isContentEditableFalse(t.from().block())&&!1===Oo.isContentEditableFalse(t.to().block()));var t,n,r})},Ul=function(e,t,n){return n.collapsed?zl(e,t,n):A.none()},ql=function(e,t,n){return Mr.contains(t,e)?$r.parents(e,function(e){return n(e)||Mr.eq(e,t)}).slice(0,-1):[]},Vl=function(e,t){return ql(e,t,V.constant(!1))},Hl=Vl,jl=function(e,t){return[e].concat(Vl(e,t))},$l=function(e){var t,n,r=(t=e,n=$r.children(t),H.findIndex(n,mo).fold(function(){return n},function(e){return n.slice(0,e)}));return H.each(r,function(e){Hc.remove(e)}),r},Wl=function(e,t){Qa.positionIn(e,t.dom()).each(function(e){var t=e.getNode();Oo.isBr(t)&&Hc.remove(Vn.fromDom(t))})},Kl=function(e,t){var n=jl(t,e);return H.find(n.reverse(),Ll).each(Hc.remove)},Xl=function(o,i){return Mr.contains(i,o)?$r.parent(o).bind(function(e){return Mr.eq(e,i)?A.some(o):(t=i,n=o,r=$r.parents(n,function(e){return Mr.eq(e,t)}),A.from(r[r.length-2]));var t,n,r}):A.none()},Yl=function(n,r,o){if(Ll(o))return Hc.remove(o),Ll(r)&&Kc(r),Qa.firstPositionIn(r.dom());Wl(!0,r),Wl(!1,o);var i=$l(r);return Xl(r,o).fold(function(){Kl(n,r);var e=Qa.lastPositionIn(o.dom());return H.each(i,function(e){Hu.append(o,e)}),e},function(t){var e=Qa.prevPosition(o.dom(),La.before(t.dom()));return H.each(i,function(e){Hu.before(t,e)}),Kl(n,r),e})},Gl=function(e,t,n,r){return t?Yl(e,r,n):Yl(e,n,r)},Jl=function(t,n){var e,r=Vn.fromDom(t.getBody());return(e=Ul(r.dom(),n,t.selection.getRng()).bind(function(e){return Gl(r,n,e.from().block(),e.to().block())})).each(function(e){t.selection.setRng(e.toRange())}),e.isSome()},Ql=function(e,t){var n=Vn.fromDom(t),r=V.curry(Mr.eq,e);return ul.ancestor(n,xo,r).isSome()},Zl=function(e,t){var n,r,o=Qa.prevPosition(e.dom(),La.fromRangeStart(t)).isNone(),i=Qa.nextPosition(e.dom(),La.fromRangeEnd(t)).isNone();return!(Ql(n=e,(r=t).startContainer)||Ql(n,r.endContainer))&&o&&i},ef=function(e){var n,r,o,t,i=Vn.fromDom(e.getBody()),a=e.selection.getRng();return Zl(i,a)?((t=e).setContent(""),t.selection.setCursorLocation(),!0):(n=i,r=e.selection,o=r.getRng(),ma([wl(n,Vn.fromDom(o.startContainer)),wl(n,Vn.fromDom(o.endContainer))],function(e,t){return!1===Mr.eq(e,t)&&(o.deleteContents(),Gl(n,!0,e,t).each(function(e){r.setRng(e.toRange())}),!0)}).getOr(!1))},tf=function(e,t){return!e.selection.isCollapsed()&&ef(e)},nf=function(a){if(!k.isArray(a))throw new Error("cases must be an array");if(0===a.length)throw new Error("there must be at least one case");var u=[],n={};return H.each(a,function(e,r){var t=ir.keys(e);if(1!==t.length)throw new Error("one and only one name per case");var o=t[0],i=e[o];if(n[o]!==undefined)throw new Error("duplicate key detected:"+o);if("cata"===o)throw new Error("cannot have a case named cata (sorry)");if(!k.isArray(i))throw new Error("case arguments must be an array");u.push(o),n[o]=function(){var e=arguments.length;if(e!==i.length)throw new Error("Wrong number of arguments to case "+o+". Expected "+i.length+" ("+i+"), got "+e);for(var n=new Array(e),t=0;t<n.length;t++)n[t]=arguments[t];return{fold:function(){if(arguments.length!==a.length)throw new Error("Wrong number of arguments to fold. Expected "+a.length+", got "+arguments.length);return arguments[r].apply(null,n)},match:function(e){var t=ir.keys(e);if(u.length!==t.length)throw new Error("Wrong number of arguments to match. Expected: "+u.join(",")+"\nActual: "+t.join(","));if(!H.forall(u,function(e){return H.contains(t,e)}))throw new Error("Not all branches were specified when using match. Specified: "+t.join(", ")+"\nRequired: "+u.join(", "));return e[o].apply(null,n)},log:function(e){console.log(e,{constructors:u,constructor:o,params:n})}}}}),n},rf=nf([{remove:["element"]},{moveToElement:["element"]},{moveToPosition:["position"]}]),of=function(e,t,n,r){var o=r.getNode(!1===t);return wl(Vn.fromDom(e),Vn.fromDom(n.getNode())).map(function(e){return Ll(e)?rf.remove(e.dom()):rf.moveToElement(o)}).orThunk(function(){return A.some(rf.moveToElement(o))})},af=function(u,s,c){return Qa.fromPosition(s,u,c).bind(function(e){return a=e.getNode(),xo(Vn.fromDom(a))||yo(Vn.fromDom(a))?A.none():(t=u,o=e,i=function(e){return po(Vn.fromDom(e))&&!bs(r,o,t)},As(!(n=s),r=c).fold(function(){return As(n,o).fold(V.constant(!1),i)},i)?A.none():s&&Oo.isContentEditableFalse(e.getNode())?of(u,s,c,e):!1===s&&Oo.isContentEditableFalse(e.getNode(!0))?of(u,s,c,e):s&&Bs(c)?A.some(rf.moveToPosition(e)):!1===s&&_s(c)?A.some(rf.moveToPosition(e)):A.none());var t,n,r,o,i,a})},uf=function(r,e,o){return i=e,a=o.getNode(!1===i),u=i?"after":"before",Oo.isElement(a)&&a.getAttribute("data-mce-caret")===u?(t=e,n=o.getNode(!1===e),t&&Oo.isContentEditableFalse(n.nextSibling)?A.some(rf.moveToElement(n.nextSibling)):!1===t&&Oo.isContentEditableFalse(n.previousSibling)?A.some(rf.moveToElement(n.previousSibling)):A.none()).fold(function(){return af(r,e,o)},A.some):af(r,e,o).bind(function(e){return t=r,n=o,e.fold(function(e){return A.some(rf.remove(e))},function(e){return A.some(rf.moveToElement(e))},function(e){return bs(n,e,t)?A.none():A.some(rf.moveToPosition(e))});var t,n});var t,n,i,a,u},sf=function(e,t){return r=e,o=(n=t).container(),i=n.offset(),!1===La.isTextPosition(n)&&o===r.parentNode&&i>La.before(r).offset()?La(t.container(),t.offset()-1):t;var n,r,o,i},cf=function(e){return Ji(e.previousSibling)?A.some((t=e.previousSibling,Oo.isText(t)?La(t,t.data.length):La.after(t))):e.previousSibling?Qa.lastPositionIn(e.previousSibling):A.none();var t},lf=function(e){return Ji(e.nextSibling)?A.some((t=e.nextSibling,Oo.isText(t)?La(t,0):La.before(t))):e.nextSibling?Qa.firstPositionIn(e.nextSibling):A.none();var t},ff=function(r,o){return cf(o).orThunk(function(){return lf(o)}).orThunk(function(){return e=r,t=o,n=La.before(t.previousSibling?t.previousSibling:t.parentNode),Qa.prevPosition(e,n).fold(function(){return Qa.nextPosition(e,La.after(t))},A.some);var e,t,n})},df=function(n,r){return lf(r).orThunk(function(){return cf(r)}).orThunk(function(){return e=n,t=r,Qa.nextPosition(e,La.after(t)).fold(function(){return Qa.prevPosition(e,La.before(t))},A.some);var e,t})},mf=function(e,t,n){return(r=e,o=t,i=n,r?df(o,i):ff(o,i)).map(V.curry(sf,n));var r,o,i},pf=function(t,n,e){e.fold(function(){t.focus()},function(e){t.selection.setRng(e.toRange(),n)})},gf=function(e,t){return t&&e.schema.getBlockElements().hasOwnProperty(Zn.name(t))},hf=function(e){if(Ll(e)){var t=Vn.fromHtml('<br data-mce-bogus="1">');return Hc.empty(e),Hu.append(e,t),A.some(La.before(t.dom()))}return A.none()},vf=function(t,n,e){var r,a,o,i=mf(n,t.getBody(),e.dom()),u=ul.ancestor(e,V.curry(gf,t),(r=t.getBody(),function(e){return e.dom()===r})),s=(a=e,o=i,ma([$r.prevSibling(a),$r.nextSibling(a),o],function(e,t,n){var r,o=e.dom(),i=t.dom();return Oo.isText(o)&&Oo.isText(i)?(r=o.data.length,o.appendData(i.data),Hc.remove(t),Hc.remove(a),n.container()===i?La(o,r):n):(Hc.remove(a),n)}).orThunk(function(){return Hc.remove(a),o}));t.dom.isEmpty(t.getBody())?(t.setContent(""),t.selection.setCursorLocation()):u.bind(hf).fold(function(){pf(t,n,s)},function(e){pf(t,n,A.some(e))})},yf=function(a,u){var e,t,n,r,o;return(e=a.getBody(),t=u,n=a.selection.getRng(),r=Ss(t?1:-1,e,n),o=La.fromRangeStart(r),!1===t&&Bs(o)?A.some(rf.remove(o.getNode(!0))):t&&_s(o)?A.some(rf.remove(o.getNode())):uf(e,t,o)).map(function(e){return e.fold((o=a,i=u,function(e){return o._selectionOverrides.hideFakeCaret(),vf(o,i,Vn.fromDom(e)),!0}),(n=a,r=u,function(e){var t=r?La.before(e):La.after(e);return n.selection.setRng(t.toRange()),!0}),(t=a,function(e){return t.selection.setRng(e.toRange()),!0}));var t,n,r,o,i}).getOr(!1)},bf=function(e,t){var n,r=e.selection.getNode();return!!Oo.isContentEditableFalse(r)&&(n=Vn.fromDom(e.getBody()),H.each(hu(n,".mce-offscreen-selection"),Hc.remove),vf(e,t,Vn.fromDom(e.selection.getNode())),Nl(e),!0)},Cf=function(e,t){return e.selection.isCollapsed()?yf(e,t):bf(e,t)},xf=function(e){var t,n=function(e,t){for(;t&&t!==e;){if(Oo.isContentEditableTrue(t)||Oo.isContentEditableFalse(t))return t;t=t.parentNode}return null}(e.getBody(),e.selection.getNode());return Oo.isContentEditableTrue(n)&&e.dom.isBlock(n)&&e.dom.isEmpty(n)&&(t=e.dom.create("br",{"data-mce-bogus":"1"}),e.dom.setHTML(n,""),n.appendChild(t),e.selection.setRng(La.before(t).toRange())),!0},wf=Oo.isText,Nf=function(e){return wf(e)&&e.data[0]===Ri},Ef=function(e){return wf(e)&&e.data[e.data.length-1]===Ri},Sf=function(e){return e.ownerDocument.createTextNode(Ri)},kf=function(e,t){return e?function(e){if(wf(e.previousSibling))return Ef(e.previousSibling)||e.previousSibling.appendData(Ri),e.previousSibling;if(wf(e))return Nf(e)||e.insertData(0,Ri),e;var t=Sf(e);return e.parentNode.insertBefore(t,e),t}(t):function(e){if(wf(e.nextSibling))return Nf(e.nextSibling)||e.nextSibling.insertData(0,Ri),e.nextSibling;if(wf(e))return Ef(e)||e.appendData(Ri),e;var t=Sf(e);return e.nextSibling?e.parentNode.insertBefore(t,e.nextSibling):e.parentNode.appendChild(t),t}(t)},Tf=V.curry(kf,!0),Af=V.curry(kf,!1),Rf=function(e,t){return Oo.isText(e.container())?kf(t,e.container()):kf(t,e.getNode())},_f=function(e,t){var n=t.get();return n&&e.container()===n&&Pi(n)},Bf=function(n,e){return e.fold(function(e){$a.remove(n.get());var t=Tf(e);return n.set(t),A.some(La(t,t.length-1))},function(e){return Qa.firstPositionIn(e).map(function(e){if(_f(e,n))return La(n.get(),1);$a.remove(n.get());var t=Rf(e,!0);return n.set(t),La(t,1)})},function(e){return Qa.lastPositionIn(e).map(function(e){if(_f(e,n))return La(n.get(),n.get().length-1);$a.remove(n.get());var t=Rf(e,!1);return n.set(t),La(t,t.length-1)})},function(e){$a.remove(n.get());var t=Af(e);return n.set(t),A.some(La(t,1))})},Df=function(e,t){for(var n=0;n<e.length;n++){var r=e[n].apply(null,t);if(r.isSome())return r}return A.none()},Of=nf([{before:["element"]},{start:["element"]},{end:["element"]},{after:["element"]}]),Pf=function(e,t){var n=ys(t,e);return n||e},Lf=function(e,t,n){var r=xl.normalizeForwards(n),o=Pf(t,r.container());return xl.findRootInline(e,o,r).fold(function(){return Qa.nextPosition(o,r).bind(V.curry(xl.findRootInline,e,o)).map(function(e){return Of.before(e)})},A.none)},If=function(e,t){return null===Tc(e,t)},Mf=function(e,t,n){return xl.findRootInline(e,t,n).filter(V.curry(If,t))},Ff=function(e,t,n){var r=xl.normalizeBackwards(n);return Mf(e,t,r).bind(function(e){return Qa.prevPosition(e,r).isNone()?A.some(Of.start(e)):A.none()})},zf=function(e,t,n){var r=xl.normalizeForwards(n);return Mf(e,t,r).bind(function(e){return Qa.nextPosition(e,r).isNone()?A.some(Of.end(e)):A.none()})},Uf=function(e,t,n){var r=xl.normalizeBackwards(n),o=Pf(t,r.container());return xl.findRootInline(e,o,r).fold(function(){return Qa.prevPosition(o,r).bind(V.curry(xl.findRootInline,e,o)).map(function(e){return Of.after(e)})},A.none)},qf=function(e){return!1===xl.isRtl(Hf(e))},Vf=function(e,t,n){return Df([Lf,Ff,zf,Uf],[e,t,n]).filter(qf)},Hf=function(e){return e.fold(V.identity,V.identity,V.identity,V.identity)},jf=function(e){return e.fold(V.constant("before"),V.constant("start"),V.constant("end"),V.constant("after"))},$f=function(e){return e.fold(Of.before,Of.before,Of.after,Of.after)},Wf=function(n,e,r,t,o,i){return ma([xl.findRootInline(e,r,t),xl.findRootInline(e,r,o)],function(e,t){return e!==t&&xl.hasSameParentBlock(r,e,t)?Of.after(n?e:t):i}).getOr(i)},Kf=function(e,r){return e.fold(V.constant(!0),function(e){return n=r,!(jf(t=e)===jf(n)&&Hf(t)===Hf(n));var t,n})},Xf=function(e,t){return e?t.fold(V.compose(A.some,Of.start),A.none,V.compose(A.some,Of.after),A.none):t.fold(A.none,V.compose(A.some,Of.before),A.none,V.compose(A.some,Of.end))},Yf=function(a,u,s,c){var e=xl.normalizePosition(a,c),l=Vf(u,s,e);return Vf(u,s,e).bind(V.curry(Xf,a)).orThunk(function(){return t=a,n=u,r=s,o=l,e=c,i=xl.normalizePosition(t,e),Qa.fromPosition(t,r,i).map(V.curry(xl.normalizePosition,t)).fold(function(){return o.map($f)},function(e){return Vf(n,r,e).map(V.curry(Wf,t,n,r,i,e)).filter(V.curry(Kf,o))}).filter(qf);var t,n,r,o,e,i})},Gf=Vf,Jf=Yf,Qf=(V.curry(Yf,!1),V.curry(Yf,!0),$f),Zf=function(e){return e.fold(Of.start,Of.start,Of.end,Of.end)},ed=function(e){return k.isFunction(e.selection.getSel().modify)},td=function(e,t,n){var r=e?1:-1;return t.setRng(La(n.container(),n.offset()+r).toRange()),t.getSel().modify("move",e?"forward":"backward","word"),!0},nd=function(e,t){var n=t.selection.getRng(),r=e?La.fromRangeEnd(n):La.fromRangeStart(n);return!!ed(t)&&(e&&Mi(r)?td(!0,t.selection,r):!(e||!Fi(r))&&td(!1,t.selection,r))},rd=function(e,t){var n=e.dom.createRng();n.setStart(t.container(),t.offset()),n.setEnd(t.container(),t.offset()),e.selection.setRng(n)},od=function(e){return!1!==e.settings.inline_boundaries},id=function(e,t){e?t.setAttribute("data-mce-selected","inline-boundary"):t.removeAttribute("data-mce-selected")},ad=function(t,e,n){return Bf(e,n).map(function(e){return rd(t,e),n})},ud=function(e,t,n){return function(){return!!od(t)&&nd(e,t)}},sd={move:function(a,u,s){return function(){return!!od(a)&&(t=a,n=u,e=s,r=t.getBody(),o=La.fromRangeStart(t.selection.getRng()),i=V.curry(xl.isInlineTarget,t),Jf(e,i,r,o).bind(function(e){return ad(t,n,e)})).isSome();var t,n,e,r,o,i}},moveNextWord:V.curry(ud,!0),movePrevWord:V.curry(ud,!1),setupSelectedState:function(a){var u=ns(null),s=V.curry(xl.isInlineTarget,a);return a.on("NodeChange",function(e){var t,n,r,o,i;od(a)&&(t=s,n=a.dom,r=e.parents,o=H.filter(n.select('*[data-mce-selected="inline-boundary"]'),t),i=H.filter(r,t),H.each(H.difference(o,i),V.curry(id,!1)),H.each(H.difference(i,o),V.curry(id,!0)),function(e,t){if(e.selection.isCollapsed()&&!0!==e.composing&&t.get()){var n=La.fromRangeStart(e.selection.getRng());La.isTextPosition(n)&&!1===xl.isAtZwsp(n)&&(rd(e,$a.removeAndReposition(t.get(),n)),t.set(null))}}(a,u),function(n,r,o,e){if(r.selection.isCollapsed()){var t=H.filter(e,n);H.each(t,function(e){var t=La.fromRangeStart(r.selection.getRng());Gf(n,r.getBody(),t).bind(function(e){return ad(r,o,e)})})}}(s,a,u,e.parents))}),u},setCaretPosition:rd},cd=function(t,n){return function(e){return Bf(n,e).map(function(e){return sd.setCaretPosition(t,e),!0}).getOr(!1)}},ld=function(r,o,i,a){var u=r.getBody(),s=V.curry(xl.isInlineTarget,r);r.undoManager.ignore(function(){var e,t,n;r.selection.setRng((e=i,t=a,(n=document.createRange()).setStart(e.container(),e.offset()),n.setEnd(t.container(),t.offset()),n)),r.execCommand("Delete"),Gf(s,u,La.fromRangeStart(r.selection.getRng())).map(Zf).map(cd(r,o))}),r.nodeChanged()},fd=function(n,r,i,o){var e,t,a=(e=n.getBody(),t=o.container(),ys(t,e)||e),u=V.curry(xl.isInlineTarget,n),s=Gf(u,a,o);return s.bind(function(e){return i?e.fold(V.constant(A.some(Zf(e))),A.none,V.constant(A.some(Qf(e))),A.none):e.fold(A.none,V.constant(A.some(Qf(e))),A.none,V.constant(A.some(Zf(e))))}).map(cd(n,r)).getOrThunk(function(){var t=Qa.navigate(i,a,o),e=t.bind(function(e){return Gf(u,a,e)});return s.isSome()&&e.isSome()?xl.findRootInline(u,a,o).map(function(e){return o=e,!!ma([Qa.firstPositionIn(o),Qa.lastPositionIn(o)],function(e,t){var n=xl.normalizePosition(!0,e),r=xl.normalizePosition(!1,t);return Qa.nextPosition(o,n).map(function(e){return e.isEqual(r)}).getOr(!0)}).getOr(!0)&&(vf(n,i,Vn.fromDom(e)),!0);var o}).getOr(!1):e.bind(function(e){return t.map(function(e){return i?ld(n,r,o,e):ld(n,r,e,o),!0})}).getOr(!1)})},dd=function(e,t,n){if(e.selection.isCollapsed()&&!1!==e.settings.inline_boundaries){var r=La.fromRangeStart(e.selection.getRng());return fd(e,t,n,r)}return!1},md=kr.immutable("start","end"),pd=kr.immutable("rng","table","cells"),gd=nf([{removeTable:["element"]},{emptyCells:["cells"]}]),hd=function(e,t){return Al(Vn.fromDom(e),"td,th",t)},vd=function(e,t){return kl(e,"table",t)},yd=function(e){return!1===Mr.eq(e.start(),e.end())},bd=function(e,n){return vd(e.start(),n).bind(function(t){return vd(e.end(),n).bind(function(e){return Mr.eq(t,e)?A.some(t):A.none()})})},Cd=function(e){return hu(e,"td,th")},xd=function(r,e){var t=hd(e.startContainer,r),n=hd(e.endContainer,r);return e.collapsed?A.none():ma([t,n],md).fold(function(){return t.fold(function(){return n.bind(function(t){return vd(t,r).bind(function(e){return H.head(Cd(e)).map(function(e){return md(e,t)})})})},function(t){return vd(t,r).bind(function(e){return H.last(Cd(e)).map(function(e){return md(t,e)})})})},function(e){return wd(r,e)?A.none():(n=r,vd((t=e).start(),n).bind(function(e){return H.last(Cd(e)).map(function(e){return md(t.start(),e)})}));var t,n})},wd=function(e,t){return bd(t,e).isSome()},Nd=function(e,t){var n,r,o,i,a,u=(n=e,V.curry(Mr.eq,n));return(r=t,o=u,i=hd(r.startContainer,o),a=hd(r.endContainer,o),ma([i,a],md).filter(yd).filter(function(e){return wd(o,e)}).orThunk(function(){return xd(o,r)})).bind(function(e){return bd(t=e,u).map(function(e){return pd(t,e,Cd(e))});var t})},Ed=function(e,t){return H.findIndex(e,function(e){return Mr.eq(e,t)})},Sd=function(n){return(r=n,ma([Ed(r.cells(),r.rng().start()),Ed(r.cells(),r.rng().end())],function(e,t){return r.cells().slice(e,t+1)})).map(function(e){var t=n.cells();return e.length===t.length?gd.removeTable(n.table()):gd.emptyCells(e)});var r},kd=function(e,t){return Nd(e,t).bind(Sd)},Td=function(e){var t=[];if(e)for(var n=0;n<e.rangeCount;n++)t.push(e.getRangeAt(n));return t},Ad=Td,Rd=function(e){return H.bind(e,function(e){var t=aa(e);return t?[Vn.fromDom(t)]:[]})},_d=function(e){return 1<Td(e).length},Bd=function(e){return H.filter(Rd(e),xo)},Dd=function(e){return hu(e,"td[data-mce-selected],th[data-mce-selected]")},Od=function(e,t){var n=Dd(t),r=Bd(e);return 0<n.length?n:r},Pd=Od,Ld=function(e){return Od(Ad(e.selection.getSel()),Vn.fromDom(e.getBody()))},Id=function(e,t){return H.each(t,Kc),e.selection.setCursorLocation(t[0].dom(),0),!0},Md=function(e,t){return vf(e,!1,t),!0},Fd=function(n,e,r,t){return Ud(e,t).fold(function(){return t=n,kd(e,r).map(function(e){return e.fold(V.curry(Md,t),V.curry(Id,t))});var t},function(e){return qd(n,e)}).getOr(!1)},zd=function(e,t){return H.find(jl(t,e),xo)},Ud=function(e,t){return H.find(jl(t,e),function(e){return"caption"===Zn.name(e)})},qd=function(e,t){return Kc(t),e.selection.setCursorLocation(t.dom(),0),A.some(!0)},Vd=function(u,s,c,l,f){return Qa.navigate(c,u.getBody(),f).bind(function(e){return r=l,o=c,i=f,a=e,Qa.firstPositionIn(r.dom()).bind(function(t){return Qa.lastPositionIn(r.dom()).map(function(e){return o?i.isEqual(t)&&a.isEqual(e):i.isEqual(e)&&a.isEqual(t)})}).getOr(!0)?qd(u,l):(t=l,n=e,Ud(s,Vn.fromDom(n.getNode())).map(function(e){return!1===Mr.eq(e,t)}));var t,n,r,o,i,a}).or(A.some(!0))},Hd=function(a,u,s,e){var c=La.fromRangeStart(a.selection.getRng());return zd(s,e).bind(function(e){return Ll(e)?qd(a,e):(t=a,n=s,r=u,o=e,i=c,Qa.navigate(r,t.getBody(),i).bind(function(e){return zd(n,Vn.fromDom(e.getNode())).map(function(e){return!1===Mr.eq(e,o)})}));var t,n,r,o,i})},jd=function(a,u,e){var s=Vn.fromDom(a.getBody());return Ud(s,e).fold(function(){return Hd(a,u,s,e)},function(e){return t=a,n=u,r=s,o=e,i=La.fromRangeStart(t.selection.getRng()),Ll(o)?qd(t,o):Vd(t,r,n,o,i);var t,n,r,o,i}).getOr(!1)},$d=function(e,t){var n,r,o,i,a,u=Vn.fromDom(e.selection.getStart(!0)),s=Ld(e);return e.selection.isCollapsed()&&0===s.length?jd(e,t,u):(n=e,r=u,o=Vn.fromDom(n.getBody()),i=n.selection.getRng(),0!==(a=Ld(n)).length?Id(n,a):Fd(n,o,i,r))},Wd=function(e,t){e.getDoc().execCommand(t,!1,null)},Kd=function(e){Cf(e,!1)||dd(e,!1)||Jl(e,!1)||$d(e)||tf(e,!1)||(Wd(e,"Delete"),Nl(e))},Xd=function(e){Cf(e,!0)||dd(e,!0)||Jl(e,!0)||$d(e)||tf(e,!0)||Wd(e,"ForwardDelete")},Yd=function(s){return function(u,e){return A.from(e).map(Vn.fromDom).filter(Zn.isElement).bind(function(e){return(r=s,o=u,i=e.dom(),a=function(e){return Cr(e,r)},ul.closest(Vn.fromDom(i),function(e){return a(e).isSome()},function(e){return Mr.eq(Vn.fromDom(o),e)}).bind(a)).or((t=s,n=e.dom(),A.from(vi.DOM.getStyle(n,t,!0))));var t,n,r,o,i,a}).getOr("")}},Gd={getFontSize:Yd("font-size"),getFontFamily:V.compose(function(e){return e.replace(/[\'\"\\]/g,"").replace(/,\s+/g,",")},Yd("font-family")),toPt:function(e,t){return/[0-9.]+px$/.test(e)?(n=72*parseInt(e,10)/96,r=t||0,o=Math.pow(10,r),Math.round(n*o)/o+"pt"):e;var n,r,o}},Jd=function(e){return Qa.firstPositionIn(e.getBody()).map(function(e){var t=e.container();return Oo.isText(t)?t.parentNode:t})},Qd=function(o){return A.from(o.selection.getRng()).bind(function(e){var t,n,r=o.getBody();return n=r,(t=e).startContainer===n&&0===t.startOffset?A.none():A.from(o.selection.getStart(!0))})},Zd=function(e,t){if(/^[0-9\.]+$/.test(t)){var n=parseInt(t,10);if(1<=n&&n<=7){var r=zu(e),o=Uu(e);return o?o[n-1]||t:r[n-1]||t}return t}return t},em=function(e,t){return e&&t&&e.startContainer===t.startContainer&&e.startOffset===t.startOffset&&e.endContainer===t.endContainer&&e.endOffset===t.endOffset},tm=function(e,t,n){return null!==function(e,t,n){for(;e&&e!==t;){if(n(e))return e;e=e.parentNode}return null}(e,t,n)},nm=function(e,t,n){return tm(e,t,function(e){return e.nodeName===n})},rm=function(e){return e&&"TABLE"===e.nodeName},om=function(e,t,n){for(var r=new ao(t,e.getParent(t.parentNode,e.isBlock)||e.getRoot());t=r[n?"prev":"next"]();)if(Oo.isBr(t))return!0},im=function(e,t,n,r,o){var i,a,u,s,c,l,f=e.getRoot(),d=e.schema.getNonEmptyElements();if(u=e.getParent(o.parentNode,e.isBlock)||f,r&&Oo.isBr(o)&&t&&e.isEmpty(u))return A.some(Da(o.parentNode,e.nodeIndex(o)));for(i=new ao(o,u);s=i[r?"prev":"next"]();){if("false"===e.getContentEditableParent(s)||(l=f,Li(c=s)&&!1===tm(c,l,kc)))return A.none();if(Oo.isText(s)&&0<s.nodeValue.length)return!1===nm(s,f,"A")?A.some(Da(s,r?s.nodeValue.length:0)):A.none();if(e.isBlock(s)||d[s.nodeName.toLowerCase()])return A.none();a=s}return n&&a?A.some(Da(a,0)):A.none()},am=function(e,t,n,r){var o,i,a,u,s,c,l,f,d,m,p=e.getRoot(),g=!1;if(o=r[(n?"start":"end")+"Container"],i=r[(n?"start":"end")+"Offset"],l=Oo.isElement(o)&&i===o.childNodes.length,s=e.schema.getNonEmptyElements(),c=n,Li(o))return A.none();if(Oo.isElement(o)&&i>o.childNodes.length-1&&(c=!1),Oo.isDocument(o)&&(o=p,i=0),o===p){if(c&&(u=o.childNodes[0<i?i-1:0])){if(Li(u))return A.none();if(s[u.nodeName]||rm(u))return A.none()}if(o.hasChildNodes()){if(i=Math.min(!c&&0<i?i-1:i,o.childNodes.length-1),o=o.childNodes[i],i=Oo.isText(o)&&l?o.data.length:0,!t&&o===p.lastChild&&rm(o))return A.none();if(function(e,t){for(;t&&t!==e;){if(Oo.isContentEditableFalse(t))return!0;t=t.parentNode}return!1}(p,o)||Li(o))return A.none();if(o.hasChildNodes()&&!1===rm(o)){a=new ao(u=o,p);do{if(Oo.isContentEditableFalse(u)||Li(u)){g=!1;break}if(Oo.isText(u)&&0<u.nodeValue.length){i=c?0:u.nodeValue.length,o=u,g=!0;break}if(s[u.nodeName.toLowerCase()]&&(!(f=u)||!/^(TD|TH|CAPTION)$/.test(f.nodeName))){i=e.nodeIndex(u),o=u.parentNode,c||i++,g=!0;break}}while(u=c?a.next():a.prev())}}}return t&&(Oo.isText(o)&&0===i&&im(e,l,t,!0,o).each(function(e){o=e.container(),i=e.offset(),g=!0}),Oo.isElement(o)&&((u=o.childNodes[i])||(u=o.childNodes[i-1]),!u||!Oo.isBr(u)||(m="A",(d=u).previousSibling&&d.previousSibling.nodeName===m)||om(e,u,!1)||om(e,u,!0)||im(e,l,t,!0,u).each(function(e){o=e.container(),i=e.offset(),g=!0}))),c&&!t&&Oo.isText(o)&&i===o.nodeValue.length&&im(e,l,t,!1,o).each(function(e){o=e.container(),i=e.offset(),g=!0}),g?A.some(Da(o,i)):A.none()},um=function(e,t){var n=t.collapsed,r=t.cloneRange(),o=Da.fromRangeStart(t);return am(e,n,!0,r).each(function(e){n&&Da.isAbove(o,e)||r.setStart(e.container(),e.offset())}),n||am(e,n,!1,r).each(function(e){r.setEnd(e.container(),e.offset())}),n&&r.collapse(!0),em(t,r)?A.none():A.some(r)},sm=function(e,t,n){var r=e.create("span",{}," ");n.parentNode.insertBefore(r,n),t.scrollIntoView(r),e.remove(r)},cm=function(e,t,n,r){var o=e.createRng();r?(o.setStartBefore(n),o.setEndBefore(n)):(o.setStartAfter(n),o.setEndAfter(n)),t.setRng(o)},lm=function(e,t){var n,r,o=e.selection,i=e.dom,a=o.getRng();um(i,a).each(function(e){a.setStart(e.startContainer,e.startOffset),a.setEnd(e.endContainer,e.endOffset)});var u=a.startOffset,s=a.startContainer;if(1===s.nodeType&&s.hasChildNodes()){var c=u>s.childNodes.length-1;s=s.childNodes[Math.min(u,s.childNodes.length-1)]||s,u=c&&3===s.nodeType?s.nodeValue.length:0}var l=i.getParent(s,i.isBlock),f=l?i.getParent(l.parentNode,i.isBlock):null,d=f?f.nodeName.toUpperCase():"",m=t&&t.ctrlKey;"LI"!==d||m||(l=f),s&&3===s.nodeType&&u>=s.nodeValue.length&&(function(e,t,n){for(var r,o=new ao(t,n),i=e.getNonEmptyElements();r=o.next();)if(i[r.nodeName.toLowerCase()]||0<r.length)return!0}(e.schema,s,l)||(n=i.create("br"),a.insertNode(n),a.setStartAfter(n),a.setEndAfter(n),r=!0)),n=i.create("br"),a.insertNode(n),sm(i,o,n),cm(i,o,n,r),e.undoManager.add()},fm=function(e,t){var n=Vn.fromTag("br");Hu.before(Vn.fromDom(t),n),e.undoManager.add()},dm=function(e,t){mm(e.getBody(),t)||Hu.after(Vn.fromDom(t),Vn.fromTag("br"));var n=Vn.fromTag("br");Hu.after(Vn.fromDom(t),n),sm(e.dom,e.selection,n.dom()),cm(e.dom,e.selection,n.dom(),!1),e.undoManager.add()},mm=function(e,t){return n=La.after(t),!!Oo.isBr(n.getNode())||Qa.nextPosition(e,La.after(t)).map(function(e){return Oo.isBr(e.getNode())}).getOr(!1);var n},pm=function(e){return e&&"A"===e.nodeName&&"href"in e},gm=function(e){return e.fold(V.constant(!1),pm,pm,V.constant(!1))},hm=function(e,t){t.fold(V.noop,V.curry(fm,e),V.curry(dm,e),V.noop)},vm=function(e,t){var n,r,o,i=(n=e,r=V.curry(xl.isInlineTarget,n),o=La.fromRangeStart(n.selection.getRng()),Gf(r,n.getBody(),o).filter(gm));i.isSome()?i.each(V.curry(hm,e)):lm(e,t)},ym=nf([{before:["element"]},{on:["element","offset"]},{after:["element"]}]),bm=(ym.before,ym.on,ym.after,function(e){return e.fold(V.identity,V.identity,V.identity)}),Cm=nf([{domRange:["rng"]},{relative:["startSitu","finishSitu"]},{exact:["start","soffset","finish","foffset"]}]),xm=kr.immutable("start","soffset","finish","foffset"),wm={domRange:Cm.domRange,relative:Cm.relative,exact:Cm.exact,exactFromRange:function(e){return Cm.exact(e.start(),e.soffset(),e.finish(),e.foffset())},range:xm,getWin:function(e){var t=e.match({domRange:function(e){return Vn.fromDom(e.startContainer)},relative:function(e,t){return bm(e)},exact:function(e,t,n,r){return e}});return $r.defaultView(t)}},Nm=Un.detect().browser,Em=function(e,t){var n=Zn.isText(t)?$c(t).length:$r.children(t).length+1;return n<e?n:e<0?0:e},Sm=function(e){return wm.range(e.start(),Em(e.soffset(),e.start()),e.finish(),Em(e.foffset(),e.finish()))},km=function(e,t){return Mr.contains(e,t)||Mr.eq(e,t)},Tm=function(t){return function(e){return km(t,e.start())&&km(t,e.finish())}},Am=function(e){return!0===e.inline||Nm.isIE()},Rm=function(e){return wm.range(Vn.fromDom(e.startContainer),e.startOffset,Vn.fromDom(e.endContainer),e.endOffset)},_m=function(e){var t=e.getSelection();return(t&&0!==t.rangeCount?A.from(t.getRangeAt(0)):A.none()).map(Rm)},Bm=function(e){var t=$r.defaultView(e);return _m(t.dom()).filter(Tm(e))},Dm=function(e,t){return A.from(t).filter(Tm(e)).map(Sm)},Om=function(e){var t=document.createRange();try{return t.setStart(e.start().dom(),e.soffset()),t.setEnd(e.finish().dom(),e.foffset()),A.some(t)}catch(n){return A.none()}},Pm=function(e){return(e.bookmark?e.bookmark:A.none()).bind(V.curry(Dm,Vn.fromDom(e.getBody()))).bind(Om)},Lm=function(e){var t=Am(e)?Bm(Vn.fromDom(e.getBody())):A.none();e.bookmark=t.isSome()?t:e.bookmark},Im=function(t){Pm(t).each(function(e){t.selection.setRng(e)})},Mm=Pm,Fm=function(e,t){var n=e.settings,r=e.dom,o=e.selection,i=e.formatter,a=/[a-z%]+$/i.exec(n.indentation)[0],u=parseInt(n.indentation,10),s=e.getParam("indent_use_margin",!1);e.queryCommandState("InsertUnorderedList")||e.queryCommandState("InsertOrderedList")||(n.forced_root_block||r.getParent(o.getNode(),r.isBlock)||i.apply("div"),H.each(o.getSelectedBlocks(),function(e){return function(e,t,n,r,o,i){if("false"!==e.getContentEditable(i)&&"LI"!==i.nodeName){var a=n?"margin":"padding";if(a="TABLE"===i.nodeName?"margin":a,a+="rtl"===e.getStyle(i,"direction",!0)?"Right":"Left","outdent"===t){var u=Math.max(0,parseInt(i.style[a]||0,10)-r);e.setStyle(i,a,u?u+o:"")}else u=parseInt(i.style[a]||0,10)+r+o,e.setStyle(i,a,u)}}(r,t,s,u,a,e)}))},zm=It.each,Um=It.extend,qm=It.map,Vm=It.inArray;function Hm(s){var o,i,a,t,c={state:{},exec:{},value:{}},n=s.settings;s.on("PreInit",function(){o=s.dom,i=s.selection,n=s.settings,a=s.formatter});var r=function(e){var t;if(!s.quirks.isHidden()&&!s.removed){if(e=e.toLowerCase(),t=c.state[e])return t(e);try{return s.getDoc().queryCommandState(e)}catch(n){}return!1}},e=function(e,n){n=n||"exec",zm(e,function(t,e){zm(e.toLowerCase().split(","),function(e){c[n][e]=t})})},u=function(e,t,n){e=e.toLowerCase(),c.value[e]=function(){return t.call(n||s)}};Um(this,{execCommand:function(t,n,r,e){var o,i,a=!1;if(!s.removed){if(/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(t)||e&&e.skip_focus?Im(s):s.focus(),(e=s.fire("BeforeExecCommand",{command:t,ui:n,value:r})).isDefaultPrevented())return!1;if(i=t.toLowerCase(),o=c.exec[i])return o(i,n,r),s.fire("ExecCommand",{command:t,ui:n,value:r}),!0;if(zm(s.plugins,function(e){if(e.execCommand&&e.execCommand(t,n,r))return s.fire("ExecCommand",{command:t,ui:n,value:r}),!(a=!0)}),a)return a;if(s.theme&&s.theme.execCommand&&s.theme.execCommand(t,n,r))return s.fire("ExecCommand",{command:t,ui:n,value:r}),!0;try{a=s.getDoc().execCommand(t,n,r)}catch(u){}return!!a&&(s.fire("ExecCommand",{command:t,ui:n,value:r}),!0)}},queryCommandState:r,queryCommandValue:function(e){var t;if(!s.quirks.isHidden()&&!s.removed){if(e=e.toLowerCase(),t=c.value[e])return t(e);try{return s.getDoc().queryCommandValue(e)}catch(n){}}},queryCommandSupported:function(e){if(e=e.toLowerCase(),c.exec[e])return!0;try{return s.getDoc().queryCommandSupported(e)}catch(t){}return!1},addCommands:e,addCommand:function(e,o,i){e=e.toLowerCase(),c.exec[e]=function(e,t,n,r){return o.call(i||s,t,n,r)}},addQueryStateHandler:function(e,t,n){e=e.toLowerCase(),c.state[e]=function(){return t.call(n||s)}},addQueryValueHandler:u,hasCustomCommand:function(e){return e=e.toLowerCase(),!!c.exec[e]}});var l=function(e,t,n){return t===undefined&&(t=!1),n===undefined&&(n=null),s.getDoc().execCommand(e,t,n)},f=function(e){return a.match(e)},d=function(e,t){a.toggle(e,t?{value:t}:undefined),s.nodeChanged()},m=function(e){t=i.getBookmark(e)},p=function(){i.moveToBookmark(t)};e({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){s.undoManager.add()},"Cut,Copy,Paste":function(e){var t,n=s.getDoc();try{l(e)}catch(o){t=!0}if("paste"!==e||n.queryCommandEnabled(e)||(t=!0),t||!n.queryCommandSupported(e)){var r=s.translate("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.");ve.mac&&(r=r.replace(/Ctrl\+/g,"\u2318+")),s.notificationManager.open({text:r,type:"error"})}},unlink:function(){if(i.isCollapsed()){var e=s.dom.getParent(s.selection.getStart(),"a");e&&s.dom.remove(e,!0)}else a.remove("link")},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone":function(e){var t=e.substring(7);"full"===t&&(t="justify"),zm("left,center,right,justify".split(","),function(e){t!==e&&a.remove("align"+e)}),"none"!==t&&d("align"+t)},"InsertUnorderedList,InsertOrderedList":function(e){var t,n;l(e),(t=o.getParent(i.getNode(),"ol,ul"))&&(n=t.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(n.nodeName)&&(m(),o.split(n,t),p()))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){d(e)},"ForeColor,HiliteColor":function(e,t,n){d(e,n)},FontName:function(e,t,n){var r,o;o=n,(r=s).formatter.toggle("fontname",{value:Zd(r,o)}),r.nodeChanged()},FontSize:function(e,t,n){var r,o;o=n,(r=s).formatter.toggle("fontsize",{value:Zd(r,o)}),r.nodeChanged()},RemoveFormat:function(e){a.remove(e)},mceBlockQuote:function(){d("blockquote")},FormatBlock:function(e,t,n){return d(n||"p")},mceCleanup:function(){var e=i.getBookmark();s.setContent(s.getContent()),i.moveToBookmark(e)},mceRemoveNode:function(e,t,n){var r=n||i.getNode();r!==s.getBody()&&(m(),s.dom.remove(r,!0),p())},mceSelectNodeDepth:function(e,t,n){var r=0;o.getParent(i.getNode(),function(e){if(1===e.nodeType&&r++===n)return i.select(e),!1},s.getBody())},mceSelectNode:function(e,t,n){i.select(n)},mceInsertContent:function(e,t,n){nl(s,n)},mceInsertRawHTML:function(e,t,n){var r=s.getContent();i.setContent("tiny_mce_marker"),s.setContent(r.replace(/tiny_mce_marker/g,function(){return n}))},mceToggleFormat:function(e,t,n){d(n)},mceSetContent:function(e,t,n){s.setContent(n)},"Indent,Outdent":function(e){Fm(s,e)},mceRepaint:function(){},InsertHorizontalRule:function(){s.execCommand("mceInsertContent",!1,"<hr />")},mceToggleVisualAid:function(){s.hasVisual=!s.hasVisual,s.addVisual()},mceReplaceContent:function(e,t,n){s.execCommand("mceInsertContent",!1,n.replace(/\{\$selection\}/g,i.getContent({format:"text"})))},mceInsertLink:function(e,t,n){var r;"string"==typeof n&&(n={href:n}),r=o.getParent(i.getNode(),"a"),n.href=n.href.replace(" ","%20"),r&&n.href||a.remove("link"),n.href&&a.apply("link",n,r)},selectAll:function(){var e=o.getParent(i.getStart(),Oo.isContentEditableTrue);if(e){var t=o.createRng();t.selectNodeContents(e),i.setRng(t)}},"delete":function(){Kd(s)},forwardDelete:function(){Xd(s)},mceNewDocument:function(){s.setContent("")},InsertLineBreak:function(e,t,n){return vm(s,n),!0}});var g=function(n){return function(){var e=i.isCollapsed()?[o.getParent(i.getNode(),o.isBlock)]:i.getSelectedBlocks(),t=qm(e,function(e){return!!a.matchNode(e,n)});return-1!==Vm(t,!0)}};e({JustifyLeft:g("alignleft"),JustifyCenter:g("aligncenter"),JustifyRight:g("alignright"),JustifyFull:g("alignjustify"),"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){return f(e)},mceBlockQuote:function(){return f("blockquote")},Outdent:function(){var e;if(n.inline_styles){if((e=o.getParent(i.getStart(),o.isBlock))&&0<parseInt(e.style.paddingLeft,10))return!0;if((e=o.getParent(i.getEnd(),o.isBlock))&&0<parseInt(e.style.paddingLeft,10))return!0}return r("InsertUnorderedList")||r("InsertOrderedList")||!n.inline_styles&&!!o.getParent(i.getNode(),"BLOCKQUOTE")},"InsertUnorderedList,InsertOrderedList":function(e){var t=o.getParent(i.getNode(),"ul,ol");return t&&("insertunorderedlist"===e&&"UL"===t.tagName||"insertorderedlist"===e&&"OL"===t.tagName)}},"state"),e({Undo:function(){s.undoManager.undo()},Redo:function(){s.undoManager.redo()}}),u("FontName",function(){return Qd(t=s).fold(function(){return Jd(t).map(function(e){return Gd.getFontFamily(t.getBody(),e)}).getOr("")},function(e){return Gd.getFontFamily(t.getBody(),e)});var t},this),u("FontSize",function(){return Qd(t=s).fold(function(){return Jd(t).map(function(e){return Gd.getFontSize(t.getBody(),e)}).getOr("")},function(e){return Gd.getFontSize(t.getBody(),e)});var t},this)}var jm=It.makeMap("focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover draggesture dragdrop drop drag submit compositionstart compositionend compositionupdate touchstart touchmove touchend"," "),$m=function(a){var u,s,c=this,l={},f=function(){return!1},d=function(){return!0};u=(a=a||{}).scope||c,s=a.toggleEvent||f;var r=function(e,t,n,r){var o,i,a;if(!1===t&&(t=f),t)for(t={func:t},r&&It.extend(t,r),a=(i=e.toLowerCase().split(" ")).length;a--;)e=i[a],(o=l[e])||(o=l[e]=[],s(e,!0)),n?o.unshift(t):o.push(t);return c},m=function(e,t){var n,r,o,i,a;if(e)for(n=(i=e.toLowerCase().split(" ")).length;n--;){if(e=i[n],r=l[e],!e){for(o in l)s(o,!1),delete l[o];return c}if(r){if(t)for(a=r.length;a--;)r[a].func===t&&(r=r.slice(0,a).concat(r.slice(a+1)),l[e]=r);else r.length=0;r.length||(s(e,!1),delete l[e])}}else{for(e in l)s(e,!1);l={}}return c};c.fire=function(e,t){var n,r,o,i;if(e=e.toLowerCase(),(t=t||{}).type=e,t.target||(t.target=u),t.preventDefault||(t.preventDefault=function(){t.isDefaultPrevented=d},t.stopPropagation=function(){t.isPropagationStopped=d},t.stopImmediatePropagation=function(){t.isImmediatePropagationStopped=d},t.isDefaultPrevented=f,t.isPropagationStopped=f,t.isImmediatePropagationStopped=f),a.beforeFire&&a.beforeFire(t),n=l[e])for(r=0,o=n.length;r<o;r++){if((i=n[r]).once&&m(e,i.func),t.isImmediatePropagationStopped())return t.stopPropagation(),t;if(!1===i.func.call(u,t))return t.preventDefault(),t}return t},c.on=r,c.off=m,c.once=function(e,t,n){return r(e,t,n,{once:!0})},c.has=function(e){return e=e.toLowerCase(),!(!l[e]||0===l[e].length)}};$m.isNative=function(e){return!!jm[e.toLowerCase()]};var Wm,Km=function(n){return n._eventDispatcher||(n._eventDispatcher=new $m({scope:n,toggleEvent:function(e,t){$m.isNative(e)&&n.toggleNativeEvent&&n.toggleNativeEvent(e,t)}})),n._eventDispatcher},Xm={fire:function(e,t,n){if(this.removed&&"remove"!==e)return t;if(t=Km(this).fire(e,t,n),!1!==n&&this.parent)for(var r=this.parent();r&&!t.isPropagationStopped();)r.fire(e,t,!1),r=r.parent();return t},on:function(e,t,n){return Km(this).on(e,t,n)},off:function(e,t){return Km(this).off(e,t)},once:function(e,t){return Km(this).once(e,t)},hasEventListeners:function(e){return Km(this).has(e)}},Ym=function(e,t){var n=lr.get(e,t);return n===undefined||""===n?[]:n.split(" ")},Gm=Ym,Jm=function(e,t,n){var r=Ym(e,t).concat([n]);lr.set(e,t,r.join(" "))},Qm=function(e,t,n){var r=H.filter(Ym(e,t),function(e){return e!==n});0<r.length?lr.set(e,t,r.join(" ")):lr.remove(e,t)},Zm=function(e){return Gm(e,"class")},ep=function(e,t){return Jm(e,"class",t)},tp=function(e,t){return Qm(e,"class",t)},np=Zm,rp=ep,op=tp,ip=function(e,t){H.contains(Zm(e),t)?tp(e,t):ep(e,t)},ap=function(e){return e.dom().classList!==undefined},up=function(e,t){return ap(e)&&e.dom().classList.contains(t)},sp={add:function(e,t){ap(e)?e.dom().classList.add(t):rp(e,t)},remove:function(e,t){var n;ap(e)?e.dom().classList.remove(t):op(e,t),0===(ap(n=e)?n.dom().classList:np(n)).length&&lr.remove(n,"class")},toggle:function(e,t){return ap(e)?e.dom().classList.toggle(t):ip(e,t)},toggler:function(e,t){var n,r,o,i,a,u,s=ap(e),c=e.dom().classList;return n=function(){s?c.remove(t):op(e,t)},r=function(){s?c.add(t):rp(e,t)},o=up(e,t),i=o||!1,{on:a=function(){r(),i=!0},off:u=function(){n(),i=!1},toggle:function(){(i?u:a)()},isOn:function(){return i}}},has:up},cp=function(e,t){return e.fire("PreProcess",t)},lp=function(e,t){return e.fire("PostProcess",t)},fp=function(e){return e.fire("remove")},dp=function(e,t){return e.fire("SwitchMode",{mode:t})},mp=function(e,t,n,r){e.fire("ObjectResizeStart",{target:t,width:n,height:r})},pp=function(e,t,n,r){e.fire("ObjectResized",{target:t,width:n,height:r})},gp=function(e,t,n){try{e.getDoc().execCommand(t,!1,n)}catch(r){}},hp=function(e,t){var n,r,o;n=Vn.fromDom(e.getBody()),r="mce-content-readonly",o=t,sp.has(n,r)&&!1===o?sp.remove(n,r):o&&sp.add(n,r),t?(e.selection.controlSelection.hideResizeRect(),e.readonly=!0,e.getBody().contentEditable="false"):(e.readonly=!1,e.getBody().contentEditable="true",gp(e,"StyleWithCSS",!1),gp(e,"enableInlineTableEditing",!1),gp(e,"enableObjectResizing",!1),e.focus(),e.nodeChanged())},vp=function(e){return e.readonly?"readonly":"design"},yp=vi.DOM,bp=function(e,t){return"selectionchange"===t?e.getDoc():!e.inline&&/^mouse|touch|click|contextmenu|drop|dragover|dragend/.test(t)?e.getDoc().documentElement:e.settings.event_root?(e.eventRoot||(e.eventRoot=yp.select(e.settings.event_root)[0]),e.eventRoot):e.getBody()},Cp=function(e,t,n){var r;(r=e).hidden||r.readonly?!0===e.readonly&&n.preventDefault():e.fire(t,n)},xp=function(i,a){var e,t;if(i.delegates||(i.delegates={}),!i.delegates[a]&&!i.removed)if(e=bp(i,a),i.settings.event_root){if(Wm||(Wm={},i.editorManager.on("removeEditor",function(){var e;if(!i.editorManager.activeEditor&&Wm){for(e in Wm)i.dom.unbind(bp(i,e));Wm=null}})),Wm[a])return;t=function(e){for(var t=e.target,n=i.editorManager.get(),r=n.length;r--;){var o=n[r].getBody();(o===t||yp.isChildOf(t,o))&&Cp(n[r],a,e)}},Wm[a]=t,yp.bind(e,a,t)}else t=function(e){Cp(i,a,e)},yp.bind(e,a,t),i.delegates[a]=t},wp={bindPendingEventDelegates:function(){var t=this;It.each(t._pendingNativeEvents,function(e){xp(t,e)})},toggleNativeEvent:function(e,t){var n=this;"focus"!==e&&"blur"!==e&&(t?n.initialized?xp(n,e):n._pendingNativeEvents?n._pendingNativeEvents.push(e):n._pendingNativeEvents=[e]:n.initialized&&(n.dom.unbind(bp(n,e),e,n.delegates[e]),delete n.delegates[e]))},unbindAllNativeEvents:function(){var e,t=this,n=t.getBody(),r=t.dom;if(t.delegates){for(e in t.delegates)t.dom.unbind(bp(t,e),e,t.delegates[e]);delete t.delegates}!t.inline&&n&&r&&(n.onload=null,r.unbind(t.getWin()),r.unbind(t.getDoc())),r&&(r.unbind(n),r.unbind(t.getContainer()))}},Np=wp=It.extend({},Xm,wp),Ep=It.each,Sp=It.explode,kp={f9:120,f10:121,f11:122},Tp=It.makeMap("alt,ctrl,shift,meta,access");function Ap(i){var a={},r=[],u=function(e){var t,n,r={};for(n in Ep(Sp(e,"+"),function(e){e in Tp?r[e]=!0:/^[0-9]{2,}$/.test(e)?r.keyCode=parseInt(e,10):(r.charCode=e.charCodeAt(0),r.keyCode=kp[e]||e.toUpperCase().charCodeAt(0))}),t=[r.keyCode],Tp)r[n]?t.push(n):r[n]=!1;return r.id=t.join(","),r.access&&(r.alt=!0,ve.mac?r.ctrl=!0:r.shift=!0),r.meta&&(ve.mac?r.meta=!0:(r.ctrl=!0,r.meta=!1)),r},s=function(e,t,n,r){var o;return(o=It.map(Sp(e,">"),u))[o.length-1]=It.extend(o[o.length-1],{func:n,scope:r||i}),It.extend(o[0],{desc:i.translate(t),subpatterns:o.slice(1)})},o=function(e,t){return!!t&&t.ctrl===e.ctrlKey&&t.meta===e.metaKey&&t.alt===e.altKey&&t.shift===e.shiftKey&&!!(e.keyCode===t.keyCode||e.charCode&&e.charCode===t.charCode)&&(e.preventDefault(),!0)},c=function(e){return e.func?e.func.call(e.scope):null};i.on("keyup keypress keydown",function(t){var e,n;((n=t).altKey||n.ctrlKey||n.metaKey||"keydown"===(e=t).type&&112<=e.keyCode&&e.keyCode<=123)&&!t.isDefaultPrevented()&&(Ep(a,function(e){if(o(t,e))return r=e.subpatterns.slice(0),"keydown"===t.type&&c(e),!0}),o(t,r[0])&&(1===r.length&&"keydown"===t.type&&c(r[0]),r.shift()))}),this.add=function(e,n,r,o){var t;return"string"==typeof(t=r)?r=function(){i.execCommand(t,!1,null)}:It.isArray(t)&&(r=function(){i.execCommand(t[0],t[1],t[2])}),Ep(Sp(It.trim(e.toLowerCase())),function(e){var t=s(e,n,r,o);a[t.id]=t}),!0},this.remove=function(e){var t=s(e);return!!a[t.id]&&(delete a[t.id],!0)}}var Rp=function(e){var t=e!==undefined?e.dom():document;return A.from(t.activeElement).map(Vn.fromDom)},_p=function(e){var t=$r.owner(e).dom();return e.dom()===t.activeElement},Bp=function(t){return Rp($r.owner(t)).filter(function(e){return t.dom().contains(e.dom())})},Dp=function(t,e){return(n=e,n.collapsed?A.from(ua(n.startContainer,n.startOffset)).map(Vn.fromDom):A.none()).bind(function(e){return Co(e)?A.some(e):!1===Mr.contains(t,e)?A.some(t):A.none()});var n},Op=function(t,e){Dp(Vn.fromDom(t.getBody()),e).bind(function(e){return Qa.firstPositionIn(e.dom())}).fold(function(){t.selection.normalize()},function(e){return t.selection.setRng(e.toRange())})},Pp=function(e){if(e.setActive)try{e.setActive()}catch(t){e.focus()}else e.focus()},Lp=function(e){var t,n=e.getBody();return n&&(t=Vn.fromDom(n),_p(t)||Bp(t).isSome())},Ip=function(e){return e.inline?Lp(e):(t=e).iframeElement&&_p(Vn.fromDom(t.iframeElement));var t},Mp=function(e){return e.editorManager.setActive(e)},Fp=function(e,t){e.removed||(t?Mp(e):function(t){var e=t.selection,n=t.settings.content_editable,r=t.getBody(),o=e.getRng();t.quirks.refreshContentEditable();var i,a,u=(i=t,a=e.getNode(),i.dom.getParent(a,function(e){return"true"===i.dom.getContentEditable(e)}));if(t.$.contains(r,u))return Pp(u),Op(t,o),Mp(t);t.bookmark!==undefined&&!1===Ip(t)&&Mm(t).each(function(e){t.selection.setRng(e),o=e}),n||(ve.opera||Pp(r),t.getWin().focus()),(ve.gecko||n)&&(Pp(r),Op(t,o)),Mp(t)}(e))},zp=Ip,Up=function(e,t){return t.dom()[e]},qp=function(e,t){return parseInt(br(t,e),10)},Vp=V.curry(Up,"clientWidth"),Hp=V.curry(Up,"clientHeight"),jp=V.curry(qp,"margin-top"),$p=V.curry(qp,"margin-left"),Wp=function(e,t,n){var r,o,i,a,u,s,c,l,f,d,m=Vn.fromDom(e.getBody()),p=e.inline?m:$r.documentElement(m),g=(r=e.inline,i=t,a=n,u=(o=p).dom().getBoundingClientRect(),{x:i-(r?u.left+o.dom().clientLeft+$p(o):0),y:a-(r?u.top+o.dom().clientTop+jp(o):0)});return c=g.x,l=g.y,f=Vp(s=p),d=Hp(s),0<=c&&0<=l&&c<=f&&l<=d},Kp=function(e){var t,n=e.inline?e.getBody():e.getContentAreaContainer();return(t=n,A.from(t).map(Vn.fromDom)).map(function(e){return Mr.contains($r.owner(e),e)}).getOr(!1)};function Xp(n){var t,o=[],i=function(){var e,t=n.theme;return t&&t.getNotificationManagerImpl?t.getNotificationManagerImpl():{open:e=function(){throw new Error("Theme did not provide a NotificationManager implementation.")},close:e,reposition:e,getArgs:e}},a=function(){0<o.length&&i().reposition(o)},u=function(t){H.findIndex(o,function(e){return e===t}).each(function(e){o.splice(e,1)})},r=function(r){if(!n.removed&&Kp(n))return H.find(o,function(e){return t=i().getArgs(e),n=r,!(t.type!==n.type||t.text!==n.text||t.progressBar||t.timeout||n.progressBar||n.timeout);var t,n}).getOrThunk(function(){n.editorManager.setActive(n);var e,t=i().open(r,function(){u(t),a()});return e=t,o.push(e),a(),t})};return(t=n).on("SkinLoaded",function(){var e=t.settings.service_message;e&&r({text:e,type:"warning",timeout:0,icon:""})}),t.on("ResizeEditor ResizeWindow",function(){we.requestAnimationFrame(a)}),t.on("remove",function(){H.each(o,function(e){i().close(e)})}),{open:r,close:function(){A.from(o[0]).each(function(e){i().close(e),u(e),a()})},getNotifications:function(){return o}}}function Yp(r){var o=[],i=function(){var e,t=r.theme;return t&&t.getWindowManagerImpl?t.getWindowManagerImpl():{open:e=function(){throw new Error("Theme did not provide a WindowManager implementation.")},alert:e,confirm:e,close:e,getParams:e,setParams:e}},a=function(e,t){return function(){return t?t.apply(e,arguments):undefined}},u=function(e){var t;o.push(e),t=e,r.fire("OpenWindow",{win:t})},s=function(n){H.findIndex(o,function(e){return e===n}).each(function(e){var t;o.splice(e,1),t=n,r.fire("CloseWindow",{win:t}),0===o.length&&r.focus()})},e=function(){return A.from(o[o.length-1])};return r.on("remove",function(){H.each(o.slice(0),function(e){i().close(e)})}),{windows:o,open:function(e,t){r.editorManager.setActive(r),Lm(r);var n=i().open(e,t,s);return u(n),n},alert:function(e,t,n){var r=i().alert(e,a(n||this,t),s);u(r)},confirm:function(e,t,n){var r=i().confirm(e,a(n||this,t),s);u(r)},close:function(){e().each(function(e){i().close(e),s(e)})},getParams:function(){return e().map(i().getParams).getOr(null)},setParams:function(t){e().each(function(e){i().setParams(e,t)})},getWindows:function(){return o}}}var Gp=Si.PluginManager,Jp=function(e,t){var n=function(e,t){for(var n in Gp.urls)if(Gp.urls[n]+"/plugin"+t+".js"===e)return n;return null}(t,e.suffix);return n?"Failed to load plugin: "+n+" from url "+t:"Failed to load plugin url: "+t},Qp=function(e,t){e.notificationManager.open({type:"error",text:t})},Zp=function(e,t){e._skinLoaded?Qp(e,t):e.on("SkinLoaded",function(){Qp(e,t)})},eg=function(e,t){Zp(e,Jp(e,t))},tg=function(e,t){Zp(e,"Failed to upload image: "+t)},ng=Zp,rg=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r=window.console;r&&(r.error?r.error.apply(r,arguments):r.log.apply(r,arguments))},og=Si.PluginManager,ig=Si.ThemeManager;function ag(){return new(W.getOrDie("XMLHttpRequest"))}function ug(u,s){var r={},n=function(e,r,o,t){var i,n;(i=new ag).open("POST",s.url),i.withCredentials=s.credentials,i.upload.onprogress=function(e){t(e.loaded/e.total*100)},i.onerror=function(){o("Image upload failed due to a XHR Transport error. Code: "+i.status)},i.onload=function(){var e,t,n;i.status<200||300<=i.status?o("HTTP Error: "+i.status):(e=JSON.parse(i.responseText))&&"string"==typeof e.location?r((t=s.basePath,n=e.location,t?t.replace(/\/$/,"")+"/"+n.replace(/^\//,""):n)):o("Invalid JSON: "+i.responseText)},(n=new FormData).append("file",e.blob(),e.filename()),i.send(n)},c=function(e,t){return{url:t,blobInfo:e,status:!0}},l=function(e,t){return{url:"",blobInfo:e,status:!1,error:t}},f=function(e,t){It.each(r[e],function(e){e(t)}),delete r[e]},o=function(e,n){return e=It.grep(e,function(e){return!u.isUploaded(e.blobUri())}),ye.all(It.map(e,function(e){return u.isPending(e.blobUri())?(t=e.blobUri(),new ye(function(e){r[t]=r[t]||[],r[t].push(e)})):(o=e,i=s.handler,a=n,u.markPending(o.blobUri()),new ye(function(t){var n;try{var r=function(){n&&n.close()};i(o,function(e){r(),u.markUploaded(o.blobUri(),e),f(o.blobUri(),c(o,e)),t(c(o,e))},function(e){r(),u.removeFailed(o.blobUri()),f(o.blobUri(),l(o,e)),t(l(o,e))},function(e){e<0||100<e||(n||(n=a()),n.progressBar.value(e))})}catch(e){t(l(o,e.message))}}));var o,i,a,t}))};return s=It.extend({credentials:!1,handler:n},s),{upload:function(e,t){return s.url||s.handler!==n?o(e,t):new ye(function(e){e([])})}}}function sg(e,t){return new(W.getOrDie("Blob"))(e,t)}function cg(){return new(W.getOrDie("FileReader"))}function lg(e){return new(W.getOrDie("Uint8Array"))(e)}var fg=function(e){return W.getOrDie("atob")(e)},dg=function(e){var t,n;return e=decodeURIComponent(e).split(","),(n=/data:([^;]+)/.exec(e[0]))&&(t=n[1]),{type:t,data:e[1]}},mg=function(e){return 0===e.indexOf("blob:")?(i=e,new ye(function(e,t){var n=function(){t("Cannot convert "+i+" to Blob. Resource might not exist or is inaccessible.")};try{var r=new ag;r.open("GET",i,!0),r.responseType="blob",r.onload=function(){200===this.status?e(this.response):n()},r.onerror=n,r.send()}catch(o){n()}})):0===e.indexOf("data:")?(o=e,new ye(function(e){var t,n,r;o=dg(o);try{t=fg(o.data)}catch(Dw){return void e(new sg([]))}for(n=new lg(t.length),r=0;r<n.length;r++)n[r]=t.charCodeAt(r);e(new sg([n],{type:o.type}))})):null;var i,o},pg=function(n){return new ye(function(e){var t=new cg;t.onloadend=function(){e(t.result)},t.readAsDataURL(n)})},gg=dg,hg=0,vg=function(e){return(e||"blobid")+hg++},yg=function(n,r,o,t){var i,a;0!==r.src.indexOf("blob:")?(i=gg(r.src).data,(a=n.findFirst(function(e){return e.base64()===i}))?o({image:r,blobInfo:a}):mg(r.src).then(function(e){a=n.create(vg(),e,i),n.add(a),o({image:r,blobInfo:a})},function(e){t(e)})):(a=n.getByUri(r.src))?o({image:r,blobInfo:a}):mg(r.src).then(function(t){pg(t).then(function(e){i=gg(e).data,a=n.create(vg(),t,i),n.add(a),o({image:r,blobInfo:a})})},function(e){t(e)})},bg=function(e){return e?e.getElementsByTagName("img"):[]},Cg=0,xg={uuid:function(e){return e+Cg+++(t=function(){return Math.round(4294967295*Math.random()).toString(36)},"s"+(new Date).getTime().toString(36)+t()+t()+t());var t}};function wg(u){var n,o,i,t,e,a,r,s,c,l,f=(n=[],o=da.constant,i=function(e){var t,n,r;if(!e.blob||!e.base64)throw new Error("blob and base64 representations of the image are required for BlobInfo to be created");return t=e.id||xg.uuid("blobid"),n=e.name||t,{id:o(t),name:o(n),filename:o(n+"."+(r=e.blob.type,{"image/jpeg":"jpg","image/jpg":"jpg","image/gif":"gif","image/png":"png"}[r.toLowerCase()]||"dat")),blob:o(e.blob),base64:o(e.base64),blobUri:o(e.blobUri||X.createObjectURL(e.blob)),uri:o(e.uri)}},{create:function(e,t,n,r){return i("object"==typeof e?e:{id:e,name:r,blob:t,base64:n})},add:function(e){t(e.id())||n.push(e)},get:t=function(t){return e(function(e){return e.id()===t})},getByUri:function(t){return e(function(e){return e.blobUri()===t})},findFirst:e=function(e){return Bt.filter(n,e)[0]},removeByUri:function(t){n=Bt.filter(n,function(e){return e.blobUri()!==t||(X.revokeObjectURL(e.blobUri()),!1)})},destroy:function(){Bt.each(n,function(e){X.revokeObjectURL(e.blobUri())}),n=[]}}),d=u.settings,m=(s={},c=function(e,t){return{status:e,resultUri:t}},{hasBlobUri:l=function(e){return e in s},getResultUri:function(e){var t=s[e];return t?t.resultUri:null},isPending:function(e){return!!l(e)&&1===s[e].status},isUploaded:function(e){return!!l(e)&&2===s[e].status},markPending:function(e){s[e]=c(1,null)},markUploaded:function(e,t){s[e]=c(2,t)},removeFailed:function(e){delete s[e]},destroy:function(){s={}}}),p=function(t){return function(e){return u.selection?t(e):[]}},g=function(e,t,n){for(var r=0;-1!==(r=e.indexOf(t,r))&&(e=e.substring(0,r)+n+e.substr(r+t.length),r+=n.length-t.length+1),-1!==r;);return e},h=function(e,t,n){return e=g(e,'src="'+t+'"','src="'+n+'"'),e=g(e,'data-mce-src="'+t+'"','data-mce-src="'+n+'"')},v=function(t,n){Bt.each(u.undoManager.data,function(e){"fragmented"===e.type?e.fragments=Bt.map(e.fragments,function(e){return h(e,t,n)}):e.content=h(e.content,t,n)})},y=function(){return u.notificationManager.open({text:u.translate("Image uploading..."),type:"info",timeout:-1,progressBar:!0})},b=function(e,t){f.removeByUri(e.src),v(e.src,t),u.$(e).attr({src:d.images_reuse_filename?t+"?"+(new Date).getTime():t,"data-mce-src":u.convertURL(t,"src")})},C=function(n){return a||(a=ug(m,{url:d.images_upload_url,basePath:d.images_upload_base_path,credentials:d.images_upload_credentials,handler:d.images_upload_handler})),N().then(p(function(r){var e;return e=Bt.map(r,function(e){return e.blobInfo}),a.upload(e,y).then(p(function(e){var t=Bt.map(e,function(e,t){var n=r[t].image;return e.status&&!1!==u.settings.images_replace_blob_uris?b(n,e.url):e.error&&tg(u,e.error),{element:n,status:e.status}});return n&&n(t),t}))}))},x=function(e){if(!1!==d.automatic_uploads)return C(e)},w=function(e){return!d.images_dataimg_filter||d.images_dataimg_filter(e)},N=function(){var o,i,a;return r||(o=m,i=f,a={},r={findAll:function(e,n){var t;n||(n=da.constant(!0)),t=Bt.filter(bg(e),function(e){var t=e.src;return!!ve.fileApi&&!e.hasAttribute("data-mce-bogus")&&!e.hasAttribute("data-mce-placeholder")&&!(!t||t===ve.transparentSrc)&&(0===t.indexOf("blob:")?!o.isUploaded(t):0===t.indexOf("data:")&&n(e))});var r=Bt.map(t,function(n){if(a[n.src])return new ye(function(t){a[n.src].then(function(e){if("string"==typeof e)return e;t({image:n,blobInfo:e.blobInfo})})});var e=new ye(function(e,t){yg(i,n,e,t)}).then(function(e){return delete a[e.image.src],e})["catch"](function(e){return delete a[n.src],e});return a[n.src]=e});return ye.all(r)}}),r.findAll(u.getBody(),w).then(p(function(e){return e=Bt.filter(e,function(e){return"string"!=typeof e||(ng(u,e),!1)}),Bt.each(e,function(e){v(e.image.src,e.blobInfo.blobUri()),e.image.src=e.blobInfo.blobUri(),e.image.removeAttribute("data-mce-src")}),e}))},E=function(e){return e.replace(/src="(blob:[^"]+)"/g,function(e,n){var t=m.getResultUri(n);if(t)return'src="'+t+'"';var r=f.getByUri(n);return r||(r=Bt.reduce(u.editorManager.get(),function(e,t){return e||t.editorUpload&&t.editorUpload.blobCache.getByUri(n)},null)),r?'src="data:'+r.blob().type+";base64,"+r.base64()+'"':e})};return u.on("setContent",function(){!1!==u.settings.automatic_uploads?x():N()}),u.on("RawSaveContent",function(e){e.content=E(e.content)}),u.on("getContent",function(e){e.source_view||"raw"===e.format||(e.content=E(e.content))}),u.on("PostRender",function(){u.parser.addNodeFilter("img",function(e){Bt.each(e,function(e){var t=e.attr("src");if(!f.getByUri(t)){var n=m.getResultUri(t);n&&e.attr("src",n)}})})}),{blobCache:f,uploadImages:C,uploadImagesAuto:x,scanForImages:N,destroy:function(){f.destroy(),m.destroy(),r=a=null}}}var Ng=function(e,t){return e.hasOwnProperty(t.nodeName)},Eg=function(e,t){if(Oo.isText(t)){if(0===t.nodeValue.length)return!0;if(/^\s+$/.test(t.nodeValue)&&(!t.nextSibling||Ng(e,t.nextSibling)))return!0}return!1},Sg=function(e){var t,n,r,o,i,a,u,s,c,l,f,d=e.settings,m=e.dom,p=e.selection,g=e.schema,h=g.getBlockElements(),v=p.getStart(),y=e.getBody();if(f=d.forced_root_block,v&&Oo.isElement(v)&&f&&(l=y.nodeName.toLowerCase(),g.isValidChild(l,f.toLowerCase())&&(b=h,C=y,x=v,!H.exists(Hl(Vn.fromDom(x),Vn.fromDom(C)),function(e){return Ng(b,e.dom())})))){var b,C,x,w,N;for(n=(t=p.getRng()).startContainer,r=t.startOffset,o=t.endContainer,i=t.endOffset,c=zp(e),v=y.firstChild;v;)if(w=h,N=v,Oo.isText(N)||Oo.isElement(N)&&!Ng(w,N)&&!Mc(N)){if(Eg(h,v)){v=(u=v).nextSibling,m.remove(u);continue}a||(a=m.create(f,e.settings.forced_root_block_attrs),v.parentNode.insertBefore(a,v),s=!0),v=(u=v).nextSibling,a.appendChild(u)}else a=null,v=v.nextSibling;s&&c&&(t.setStart(n,r),t.setEnd(o,i),p.setRng(t),e.nodeChanged())}},kg=function(e){e.settings.forced_root_block&&e.on("NodeChange",V.curry(Sg,e))},Tg=function(t){return $r.firstChild(t).fold(V.constant([t]),function(e){return[t].concat(Tg(e))})},Ag=function(t){return $r.lastChild(t).fold(V.constant([t]),function(e){return"br"===Zn.name(e)?$r.prevSibling(e).map(function(e){return[t].concat(Ag(e))}).getOr([]):[t].concat(Ag(e))})},Rg=function(o,e){return ma([(i=e,a=i.startContainer,u=i.startOffset,Oo.isText(a)?0===u?A.some(Vn.fromDom(a)):A.none():A.from(a.childNodes[u]).map(Vn.fromDom)),(t=e,n=t.endContainer,r=t.endOffset,Oo.isText(n)?r===n.data.length?A.some(Vn.fromDom(n)):A.none():A.from(n.childNodes[r-1]).map(Vn.fromDom))],function(e,t){var n=H.find(Tg(o),V.curry(Mr.eq,e)),r=H.find(Ag(o),V.curry(Mr.eq,t));return n.isSome()&&r.isSome()}).getOr(!1);var t,n,r,i,a,u},_g=function(e,t,n,r){var o=n,i=new ao(n,o),a=e.schema.getNonEmptyElements();do{if(3===n.nodeType&&0!==It.trim(n.nodeValue).length)return void(r?t.setStart(n,0):t.setEnd(n,n.nodeValue.length));if(a[n.nodeName]&&!/^(TD|TH)$/.test(n.nodeName))return void(r?t.setStartBefore(n):"BR"===n.nodeName?t.setEndBefore(n):t.setEndAfter(n));if(ve.ie&&ve.ie<11&&e.isBlock(n)&&e.isEmpty(n))return void(r?t.setStart(n,0):t.setEnd(n,0))}while(n=r?i.next():i.prev());"BODY"===o.nodeName&&(r?t.setStart(o,0):t.setEnd(o,o.childNodes.length))},Bg=function(e){var t=e.selection.getSel();return t&&0<t.rangeCount};function Dg(i){var r,o=[];"onselectionchange"in i.getDoc()||i.on("NodeChange Click MouseUp KeyUp Focus",function(e){var t,n;n={startContainer:(t=i.selection.getRng()).startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset},"nodechange"!==e.type&&em(n,r)||i.fire("SelectionChange"),r=n}),i.on("contextmenu",function(){i.fire("SelectionChange")}),i.on("SelectionChange",function(){var e=i.selection.getStart(!0);!e||!ve.range&&i.selection.isCollapsed()||Bg(i)&&!function(e){var t,n;if((n=i.$(e).parentsUntil(i.getBody()).add(e)).length===o.length){for(t=n.length;0<=t&&n[t]===o[t];t--);if(-1===t)return o=n,!0}return o=n,!1}(e)&&i.dom.isChildOf(e,i.getBody())&&i.nodeChanged({selectionChange:!0})}),i.on("MouseUp",function(e){!e.isDefaultPrevented()&&Bg(i)&&("IMG"===i.selection.getNode().nodeName?we.setEditorTimeout(i,function(){i.nodeChanged()}):i.nodeChanged())}),this.nodeChanged=function(e){var t,n,r,o=i.selection;i.initialized&&o&&!i.settings.disable_nodechange&&!i.readonly&&(r=i.getBody(),(t=o.getStart(!0)||r).ownerDocument===i.getDoc()&&i.dom.isChildOf(t,r)||(t=r),n=[],i.dom.getParent(t,function(e){if(e===r)return!0;n.push(e)}),(e=e||{}).element=t,e.parents=n,i.fire("NodeChange",e))}}var Og,Pg,Lg=function(e){var t,n,r,o;return o=e.getBoundingClientRect(),n=(t=e.ownerDocument).documentElement,r=t.defaultView,{top:o.top+r.pageYOffset-n.clientTop,left:o.left+r.pageXOffset-n.clientLeft}},Ig=function(e,t){return n=(u=e).inline?Lg(u.getBody()):{left:0,top:0},a=(i=e).getBody(),r=i.inline?{left:a.scrollLeft,top:a.scrollTop}:{left:0,top:0},{pageX:(o=function(e,t){if(t.target.ownerDocument!==e.getDoc()){var n=Lg(e.getContentAreaContainer()),r=(i=(o=e).getBody(),a=o.getDoc().documentElement,u={left:i.scrollLeft,top:i.scrollTop},s={left:i.scrollLeft||a.scrollLeft,top:i.scrollTop||a.scrollTop},o.inline?u:s);return{left:t.pageX-n.left+r.left,top:t.pageY-n.top+r.top}}var o,i,a,u,s;return{left:t.pageX,top:t.pageY}}(e,t)).left-n.left+r.left,pageY:o.top-n.top+r.top};var n,r,o,i,a,u},Mg=Oo.isContentEditableFalse,Fg=Oo.isContentEditableTrue,zg=function(e){e&&e.parentNode&&e.parentNode.removeChild(e)},Ug=function(u,s){return function(e){if(0===e.button){var t=Bt.find(s.dom.getParents(e.target),da.or(Mg,Fg));if(i=s.getBody(),Mg(a=t)&&a!==i){var n=s.dom.getPos(t),r=s.getBody(),o=s.getDoc().documentElement;u.element=t,u.screenX=e.screenX,u.screenY=e.screenY,u.maxX=(s.inline?r.scrollWidth:o.offsetWidth)-2,u.maxY=(s.inline?r.scrollHeight:o.offsetHeight)-2,u.relX=e.pageX-n.x,u.relY=e.pageY-n.y,u.width=t.offsetWidth,u.height=t.offsetHeight,u.ghost=function(e,t,n,r){var o=t.cloneNode(!0);e.dom.setStyles(o,{width:n,height:r}),e.dom.setAttrib(o,"data-mce-selected",null);var i=e.dom.create("div",{"class":"mce-drag-container","data-mce-bogus":"all",unselectable:"on",contenteditable:"false"});return e.dom.setStyles(i,{position:"absolute",opacity:.5,overflow:"hidden",border:0,padding:0,margin:0,width:n,height:r}),e.dom.setStyles(o,{margin:0,boxSizing:"border-box"}),i.appendChild(o),i}(s,t,u.width,u.height)}}var i,a}},qg=function(l,f){return function(e){if(l.dragging&&(s=(i=f).selection,c=s.getSel().getRangeAt(0).startContainer,a=3===c.nodeType?c.parentNode:c,u=l.element,a!==u&&!i.dom.isChildOf(a,u)&&!Mg(a))){var t=(r=l.element,(o=r.cloneNode(!0)).removeAttribute("data-mce-selected"),o),n=f.fire("drop",{targetClone:t,clientX:e.clientX,clientY:e.clientY});n.isDefaultPrevented()||(t=n.targetClone,f.undoManager.transact(function(){zg(l.element),f.insertContent(f.dom.getOuterHTML(t)),f._selectionOverrides.hideFakeCaret()}))}var r,o,i,a,u,s,c;Vg(l)}},Vg=function(e){e.dragging=!1,e.element=null,zg(e.ghost)},Hg=function(e){var t,n,r,o,i,a,g,h,v,u,s,c={};t=vi.DOM,a=document,n=Ug(c,e),g=c,h=e,v=we.throttle(function(e,t){h._selectionOverrides.hideFakeCaret(),h.selection.placeCaretAt(e,t)},0),r=function(e){var t,n,r,o,i,a,u,s,c,l,f,d,m=Math.max(Math.abs(e.screenX-g.screenX),Math.abs(e.screenY-g.screenY));if(g.element&&!g.dragging&&10<m){if(h.fire("dragstart",{target:g.element}).isDefaultPrevented())return;g.dragging=!0,h.focus()}if(g.dragging){var p=(f=g,{pageX:(d=Ig(h,e)).pageX-f.relX,pageY:d.pageY+5});c=g.ghost,l=h.getBody(),c.parentNode!==l&&l.appendChild(c),t=g.ghost,n=p,r=g.width,o=g.height,i=g.maxX,a=g.maxY,s=u=0,t.style.left=n.pageX+"px",t.style.top=n.pageY+"px",n.pageX+r>i&&(u=n.pageX+r-i),n.pageY+o>a&&(s=n.pageY+o-a),t.style.width=r-u+"px",t.style.height=o-s+"px",v(e.clientX,e.clientY)}},o=qg(c,e),u=c,i=function(){u.dragging&&s.fire("dragend"),Vg(u)},(s=e).on("mousedown",n),e.on("mousemove",r),e.on("mouseup",o),t.bind(a,"mousemove",r),t.bind(a,"mouseup",i),e.on("remove",function(){t.unbind(a,"mousemove",r),t.unbind(a,"mouseup",i)})},jg=function(e){var n;Hg(e),(n=e).on("drop",function(e){var t="undefined"!=typeof e.clientX?n.getDoc().elementFromPoint(e.clientX,e.clientY):null;(Mg(t)||Mg(n.dom.getContentEditableParent(t)))&&e.preventDefault()})},$g=function(e){return Bt.reduce(e,function(e,t){return e.concat(function(t){var e=function(e){return Bt.map(e,function(e){return(e=ta(e)).node=t,e})};if(Oo.isElement(t))return e(t.getClientRects());if(Oo.isText(t)){var n=t.ownerDocument.createRange();return n.setStart(t,0),n.setEnd(t,t.data.length),e(n.getClientRects())}}(t))},[])};(Pg=Og||(Og={}))[Pg.Up=-1]="Up",Pg[Pg.Down=1]="Down";var Wg=function(o,i,a,e,u,t){var n,s,c=0,l=[],r=function(e){var t,n,r;for(r=$g([e]),-1===o&&(r=r.reverse()),t=0;t<r.length;t++)if(n=r[t],!a(n,s)){if(0<l.length&&i(n,Bt.last(l))&&c++,n.line=c,u(n))return!0;l.push(n)}};return(s=Bt.last(t.getClientRects()))&&(r(n=t.getNode()),function(e,t,n,r){for(;r=vs(r,e,Zi,t);)if(n(r))return}(o,e,r,n)),l},Kg=V.curry(Wg,Og.Up,oa,ia),Xg=V.curry(Wg,Og.Down,ia,oa),Yg=function(n){return function(e){return t=n,e.line>t;var t}},Gg=function(n){return function(e){return t=n,e.line===t;var t}},Jg=Oo.isContentEditableFalse,Qg=vs,Zg=function(e,t){return Math.abs(e.left-t)},eh=function(e,t){return Math.abs(e.right-t)},th=function(e,t){return e>=t.left&&e<=t.right},nh=function(e,o){return Bt.reduce(e,function(e,t){var n,r;return n=Math.min(Zg(e,o),eh(e,o)),r=Math.min(Zg(t,o),eh(t,o)),th(o,t)?t:th(o,e)?e:r===n&&Jg(t.node)?t:r<n?t:e})},rh=function(e,t,n,r){for(;r=Qg(r,e,Zi,t);)if(n(r))return},oh=function(e,t,n){var r,o,i,a,u,s,c,l,f=$g((o=e,Bt.filter(Bt.toArray(o.getElementsByTagName("*")),as))),d=Bt.filter(f,function(e){return n>=e.top&&n<=e.bottom});return(r=nh(d,t))&&(r=nh((u=e,l=function(t,e){var n;return n=Bt.filter($g([e]),function(e){return!t(e,s)}),c=c.concat(n),0===n.length},(c=[]).push(s=r),rh(Og.Up,u,V.curry(l,oa),s.node),rh(Og.Down,u,V.curry(l,ia),s.node),c),t))&&as(r.node)?(a=t,{node:(i=r).node,before:Zg(i,a)<eh(i,a)}):null},ih=function(i,a,e){return!e.collapsed&&H.foldl(e.getClientRects(),function(e,t){return e||(o=a,(r=i)>=(n=t).left&&r<=n.right&&o>=n.top&&o<=n.bottom);var n,r,o},!1)},ah=function(t,n){var r=null;return{cancel:function(){null!==r&&(clearTimeout(r),r=null)},throttle:function(){var e=arguments;null===r&&(r=setTimeout(function(){t.apply(null,e),e=r=null},n))}}},uh=function(t){var e=ah(function(){if(!t.removed&&t.selection.getRng().collapsed){var e=ou(t,t.selection.getRng(),!1);t.selection.setRng(e)}},0);t.on("focus",function(){e.throttle()}),t.on("blur",function(){e.cancel()})},sh={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(e){return e.shiftKey||e.ctrlKey||e.altKey||this.metaKeyPressed(e)},metaKeyPressed:function(e){return ve.mac?e.metaKey:e.ctrlKey&&!e.altKey}},ch=Oo.isContentEditableTrue,lh=Oo.isContentEditableFalse,fh=Bs,dh=_s,mh=function(e,t){for(var n=e.getBody();t&&t!==n;){if(ch(t)||lh(t))return t;t=t.parentNode}return null},ph=function(p){var g,e,t,a=p.getBody(),o=is(p.getBody(),function(e){return p.dom.isBlock(e)},function(){return zp(p)}),h="sel-"+p.dom.uniqueId(),u=function(e){e&&p.selection.setRng(e)},s=function(){return p.selection.getRng()},v=function(e,t,n,r){return void 0===r&&(r=!0),p.fire("ShowCaret",{target:t,direction:e,before:n}).isDefaultPrevented()?null:(r&&p.selection.scrollIntoView(t,-1===e),o.show(n,t))},y=function(e,t){return t=Ss(e,a,t),-1===e?La.fromRangeStart(t):La.fromRangeEnd(t)},n=function(e){return Li(e)||Ui(e)||qi(e)},b=function(e){return n(e.startContainer)||n(e.endContainer)},c=function(e,t){var n,r,o,i,a,u,s,c,l,f,d=p.$,m=p.dom;if(!e)return null;if(e.collapsed){if(!b(e))if(!1===t){if(c=y(-1,e),as(c.getNode(!0)))return v(-1,c.getNode(!0),!1,!1);if(as(c.getNode()))return v(-1,c.getNode(),!c.isAtEnd(),!1)}else{if(c=y(1,e),as(c.getNode()))return v(1,c.getNode(),!c.isAtEnd(),!1);if(as(c.getNode(!0)))return v(1,c.getNode(!0),!1,!1)}return null}return i=e.startContainer,a=e.startOffset,u=e.endOffset,3===i.nodeType&&0===a&&lh(i.parentNode)&&(i=i.parentNode,a=m.nodeIndex(i),i=i.parentNode),1!==i.nodeType?null:(u===a+1&&(n=i.childNodes[a]),lh(n)?(l=f=n.cloneNode(!0),(s=p.fire("ObjectSelected",{target:n,targetClone:l})).isDefaultPrevented()?null:(r=Tl(Vn.fromDom(p.getBody()),"#"+h).fold(function(){return d([])},function(e){return d([e.dom()])}),l=s.targetClone,0===r.length&&(r=d('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>').attr("id",h)).appendTo(p.getBody()),e=p.dom.createRng(),l===f&&ve.ie?(r.empty().append('<p style="font-size: 0" data-mce-bogus="all">\xa0</p>').append(l),e.setStartAfter(r[0].firstChild.firstChild),e.setEndAfter(l)):(r.empty().append("\xa0").append(l).append("\xa0"),e.setStart(r[0].firstChild,1),e.setEnd(r[0].lastChild,0)),r.css({top:m.getPos(n,p.getBody()).y}),r[0].focus(),(o=p.selection.getSel()).removeAllRanges(),o.addRange(e),H.each(hu(Vn.fromDom(p.getBody()),"*[data-mce-selected]"),function(e){lr.remove(e,"data-mce-selected")}),n.setAttribute("data-mce-selected","1"),g=n,C(),e)):null)},l=function(){g&&g.removeAttribute("data-mce-selected"),Tl(Vn.fromDom(p.getBody()),"#"+h).each(Hc.remove),g=null},C=function(){o.hide()};return ve.ceFalse&&(function(){p.on("mouseup",function(e){var t=s();t.collapsed&&Wp(p,e.clientX,e.clientY)&&u(ru(p,t,!1))}),p.on("click",function(e){var t;(t=mh(p,e.target))&&(lh(t)&&(e.preventDefault(),p.focus()),ch(t)&&p.dom.isChildOf(t,p.selection.getNode())&&l())}),p.on("blur NewBlock",function(){l()}),p.on("ResizeWindow FullscreenStateChanged",function(){return o.reposition()});var n,r,i=function(e,t){var n,r,o=p.dom.getParent(e,p.dom.isBlock),i=p.dom.getParent(t,p.dom.isBlock);return!(!o||!p.dom.isChildOf(o,i)||!1!==lh(mh(p,o)))||o&&(n=o,r=i,!(p.dom.getParent(n,p.dom.isBlock)===p.dom.getParent(r,p.dom.isBlock)))&&function(e){var t=Ys(e);if(!e.firstChild)return!1;var n=La.before(e.firstChild),r=t.next(n);return r&&!dh(r)&&!fh(r)}(o)};r=!1,(n=p).on("touchstart",function(){r=!1}),n.on("touchmove",function(){r=!0}),n.on("touchend",function(e){var t=mh(n,e.target);lh(t)&&(r||(e.preventDefault(),c(nu(n,t))))}),p.on("mousedown",function(e){var t,n=e.target;if((n===a||"HTML"===n.nodeName||p.dom.isChildOf(n,a))&&!1!==Wp(p,e.clientX,e.clientY))if(t=mh(p,n))lh(t)?(e.preventDefault(),c(nu(p,t))):(l(),ch(t)&&e.shiftKey||ih(e.clientX,e.clientY,p.selection.getRng())||(C(),p.selection.placeCaretAt(e.clientX,e.clientY)));else if(!1===as(n)){l(),C();var r=oh(a,e.clientX,e.clientY);if(r&&!i(e.target,r.node)){e.preventDefault();var o=v(1,r.node,r.before,!1);p.getBody().focus(),u(o)}}}),p.on("keypress",function(e){sh.modifierPressed(e)||(e.keyCode,lh(p.selection.getNode())&&e.preventDefault())}),p.on("getSelectionRange",function(e){var t=e.range;if(g){if(!g.parentNode)return void(g=null);(t=t.cloneRange()).selectNode(g),e.range=t}}),p.on("setSelectionRange",function(e){var t;(t=c(e.range,e.forward))&&(e.range=t)}),p.on("AfterSetSelectionRange",function(e){var t,n=e.range;b(n)||C(),t=n.startContainer.parentNode,p.dom.hasClass(t,"mce-offscreen-selection")||l()}),p.on("copy",function(e){var t,n=e.clipboardData;if(!e.isDefaultPrevented()&&e.clipboardData&&!ve.ie){var r=(t=p.dom.get(h))?t.getElementsByTagName("*")[0]:t;r&&(e.preventDefault(),n.clearData(),n.setData("text/html",r.outerHTML),n.setData("text/plain",r.outerText))}}),jg(p),uh(p)}(),e=p.contentStyles,t=".mce-content-body",e.push(o.getCss()),e.push(t+" .mce-offscreen-selection {position: absolute;left: -9999999999px;max-width: 1000000px;}"+t+" *[contentEditable=false] {cursor: default;}"+t+" *[contentEditable=true] {cursor: text;}")),{showCaret:v,showBlockCaretContainer:function(e){e.hasAttribute("data-mce-caret")&&(Vi(e),u(s()),p.selection.scrollIntoView(e[0]))},hideFakeCaret:C,destroy:function(){o.destroy(),g=null}}},gh=function(e,t,n){var r,o,i,a,u=1;for(a=e.getShortEndedElements(),(i=/<([!?\/])?([A-Za-z0-9\-_\:\.]+)((?:\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\/|\s+)>/g).lastIndex=r=n;o=i.exec(t);){if(r=i.lastIndex,"/"===o[1])u--;else if(!o[1]){if(o[2]in a)continue;u++}if(0===u)break}return r};function hh(F,z){void 0===z&&(z=oi());var e=function(){};!1!==(F=F||{}).fix_self_closing&&(F.fix_self_closing=!0);var U=F.comment?F.comment:e,q=F.cdata?F.cdata:e,V=F.text?F.text:e,H=F.start?F.start:e,j=F.end?F.end:e,$=F.pi?F.pi:e,W=F.doctype?F.doctype:e;return{parse:function(e){var t,n,r,d,o,i,a,m,u,s,p,c,g,l,f,h,v,y,b,C,x,w,N,E,S,k,T,A,R,_=0,B=[],D=0,O=Ko.decode,P=It.makeMap("src,href,data,background,formaction,poster,xlink:href"),L=/((java|vb)script|mhtml):/i,I=function(e){var t,n;for(t=B.length;t--&&B[t].name!==e;);if(0<=t){for(n=B.length-1;t<=n;n--)(e=B[n]).valid&&j(e.name);B.length=t}},M=function(e,t,n,r,o){var i,a,u,s,c;if(n=(t=t.toLowerCase())in p?t:O(n||r||o||""),g&&!m&&0==(0===(u=t).indexOf("data-")||0===u.indexOf("aria-"))){if(!(i=y[t])&&b){for(a=b.length;a--&&!(i=b[a]).pattern.test(t););-1===a&&(i=null)}if(!i)return;if(i.validValues&&!(n in i.validValues))return}if(P[t]&&!F.allow_script_urls){var l=n.replace(/[\s\u0000-\u001F]+/g,"");try{l=decodeURIComponent(l)}catch(f){l=unescape(l)}if(L.test(l))return;if(c=l,!(s=F).allow_html_data_urls&&(/^data:image\//i.test(c)?!1===s.allow_svg_data_urls&&/^data:image\/svg\+xml/i.test(c):/^data:/i.test(c)))return}m&&(t in P||0===t.indexOf("on"))||(d.map[t]=n,d.push({name:t,value:n}))};for(S=new RegExp("<(?:(?:!--([\\w\\W]*?)--\x3e)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)>)|(?:([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g"),k=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g,s=z.getShortEndedElements(),E=F.self_closing_elements||z.getSelfClosingElements(),p=z.getBoolAttrs(),g=F.validate,u=F.remove_internals,R=F.fix_self_closing,T=z.getSpecialElements(),N=e+">";t=S.exec(N);){if(_<t.index&&V(O(e.substr(_,t.index-_))),n=t[6])":"===(n=n.toLowerCase()).charAt(0)&&(n=n.substr(1)),I(n);else if(n=t[7]){if(t.index+t[0].length>e.length){V(O(e.substr(t.index))),_=t.index+t[0].length;continue}if(":"===(n=n.toLowerCase()).charAt(0)&&(n=n.substr(1)),c=n in s,R&&E[n]&&0<B.length&&B[B.length-1].name===n&&I(n),!g||(l=z.getElementRule(n))){if(f=!0,g&&(y=l.attributes,b=l.attributePatterns),(v=t[8])?((m=-1!==v.indexOf("data-mce-type"))&&u&&(f=!1),(d=[]).map={},v.replace(k,M)):(d=[]).map={},g&&!m){if(C=l.attributesRequired,x=l.attributesDefault,w=l.attributesForced,l.removeEmptyAttrs&&!d.length&&(f=!1),w)for(o=w.length;o--;)a=(h=w[o]).name,"{$uid}"===(A=h.value)&&(A="mce_"+D++),d.map[a]=A,d.push({name:a,value:A});if(x)for(o=x.length;o--;)(a=(h=x[o]).name)in d.map||("{$uid}"===(A=h.value)&&(A="mce_"+D++),d.map[a]=A,d.push({name:a,value:A}));if(C){for(o=C.length;o--&&!(C[o]in d.map););-1===o&&(f=!1)}if(h=d.map["data-mce-bogus"]){if("all"===h){_=gh(z,e,S.lastIndex),S.lastIndex=_;continue}f=!1}}f&&H(n,d,c)}else f=!1;if(r=T[n]){r.lastIndex=_=t.index+t[0].length,(t=r.exec(e))?(f&&(i=e.substr(_,t.index-_)),_=t.index+t[0].length):(i=e.substr(_),_=e.length),f&&(0<i.length&&V(i,!0),j(n)),S.lastIndex=_;continue}c||(v&&v.indexOf("/")===v.length-1?f&&j(n):B.push({name:n,valid:f}))}else(n=t[1])?(">"===n.charAt(0)&&(n=" "+n),F.allow_conditional_comments||"[if"!==n.substr(0,3).toLowerCase()||(n=" "+n),U(n)):(n=t[2])?q(n.replace(/<!--|-->/g,"")):(n=t[3])?W(n):(n=t[4])&&$(n,t[5]);_=t.index+t[0].length}for(_<e.length&&V(O(e.substr(_))),o=B.length-1;0<=o;o--)(n=B[o]).valid&&j(n.name)}}}(hh||(hh={})).findEndTag=gh;var vh=hh,yh=function(e,t){var n,r,o,i,a,u,s,c,l=t,f=/<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g,d=e.schema;for(u=e.getTempAttrs(),s=l,c=new RegExp(["\\s?("+u.join("|")+')="[^"]+"'].join("|"),"gi"),l=s.replace(c,""),a=d.getShortEndedElements();i=f.exec(l);)r=f.lastIndex,o=i[0].length,n=a[i[1]]?r:vh.findEndTag(d,l,r),l=l.substring(0,r-o)+l.substring(n),f.lastIndex=r-o;return _i(l)},bh={trimExternal:yh,trimInternal:yh},Ch=0,xh=2,wh=1,Nh=function(p,g){var e=p.length+g.length+2,h=new Array(e),v=new Array(e),c=function(e,t,n,r,o){var i=l(e,t,n,r);if(null===i||i.start===t&&i.diag===t-r||i.end===e&&i.diag===e-n)for(var a=e,u=n;a<t||u<r;)a<t&&u<r&&p[a]===g[u]?(o.push([0,p[a]]),++a,++u):r-n<t-e?(o.push([2,p[a]]),++a):(o.push([1,g[u]]),++u);else{c(e,i.start,n,i.start-i.diag,o);for(var s=i.start;s<i.end;++s)o.push([0,p[s]]);c(i.end,t,i.end-i.diag,r,o)}},y=function(e,t,n,r){for(var o=e;o-t<r&&o<n&&p[o]===g[o-t];)++o;return{start:e,end:o,diag:t}},l=function(e,t,n,r){var o=t-e,i=r-n;if(0===o||0===i)return null;var a,u,s,c,l,f=o-i,d=i+o,m=(d%2==0?d:d+1)/2;for(h[1+m]=e,v[1+m]=t+1,a=0;a<=m;++a){for(u=-a;u<=a;u+=2){for(s=u+m,u===-a||u!==a&&h[s-1]<h[s+1]?h[s]=h[s+1]:h[s]=h[s-1]+1,l=(c=h[s])-e+n-u;c<t&&l<r&&p[c]===g[l];)h[s]=++c,++l;if(f%2!=0&&f-a<=u&&u<=f+a&&v[s-f]<=h[s])return y(v[s-f],u+e-n,t,r)}for(u=f-a;u<=f+a;u+=2){for(s=u+m-f,u===f-a||u!==f+a&&v[s+1]<=v[s-1]?v[s]=v[s+1]-1:v[s]=v[s-1],l=(c=v[s]-1)-e+n-u;e<=c&&n<=l&&p[c]===g[l];)v[s]=c--,l--;if(f%2==0&&-a<=u&&u<=a&&v[s]<=h[s+f])return y(v[s],u+e-n,t,r)}}},t=[];return c(0,p.length,0,g.length,t),t},Eh=function(e){return Oo.isElement(e)?e.outerHTML:Oo.isText(e)?Ko.encodeRaw(e.data,!1):Oo.isComment(e)?"\x3c!--"+e.data+"--\x3e":""},Sh=function(e,t,n){var r=function(e){var t,n,r;for(r=document.createElement("div"),t=document.createDocumentFragment(),e&&(r.innerHTML=e);n=r.firstChild;)t.appendChild(n);return t}(t);if(e.hasChildNodes()&&n<e.childNodes.length){var o=e.childNodes[n];o.parentNode.insertBefore(r,o)}else e.appendChild(r)},kh=function(e){return Bt.filter(Bt.map(e.childNodes,Eh),function(e){return 0<e.length})},Th=function(e,t){var n,r,o,i=Bt.map(t.childNodes,Eh);return n=Nh(i,e),r=t,o=0,Bt.each(n,function(e){e[0]===Ch?o++:e[0]===wh?(Sh(r,e[1],o),o++):e[0]===xh&&function(e,t){if(e.hasChildNodes()&&t<e.childNodes.length){var n=e.childNodes[t];n.parentNode.removeChild(n)}}(r,o)}),t},Ah=function(e,t){var n=(t||document).createElement("div");return n.innerHTML=e,$r.children(Vn.fromDom(n))},Rh=function(e){return e.dom().innerHTML},_h=Rh,Bh=function(e,t){var n=$r.owner(e).dom(),r=Vn.fromDom(n.createDocumentFragment()),o=Ah(t,n);qc(r,o),Hc.empty(e),Hu.append(e,r)},Dh=ns(A.none()),Oh=function(e){return{type:"fragmented",fragments:e,content:"",bookmark:null,beforeBookmark:null}},Ph=function(e){return{type:"complete",fragments:null,content:e,bookmark:null,beforeBookmark:null}},Lh=function(e){return"fragmented"===e.type?e.fragments.join(""):e.content},Ih=function(e){var t=Vn.fromTag("body",Dh.get().getOrThunk(function(){var e=document.implementation.createHTMLDocument("undo");return Dh.set(A.some(e)),e}));return Bh(t,Lh(e)),H.each(hu(t,"*[data-mce-bogus]"),Hc.unwrap),_h(t)},Mh=function(n){var e,t,r;return e=kh(n.getBody()),-1!==(t=(r=H.bind(e,function(e){var t=bh.trimInternal(n.serializer,e);return 0<t.length?[t]:[]})).join("")).indexOf("</iframe>")?Oh(r):Ph(t)},Fh=function(e,t,n){"fragmented"===t.type?Th(t.fragments,e.getBody()):e.setContent(t.content,{format:"raw"}),e.selection.moveToBookmark(n?t.beforeBookmark:t.bookmark)},zh=function(e,t){return!(!e||!t)&&(r=t,Lh(e)===Lh(r)||(n=t,Ih(e)===Ih(n)));var n,r};function Uh(u){var s,r,o=this,c=0,l=[],t=0,f=function(){return 0===t},i=function(e){f()&&(o.typing=e)},d=function(e){u.setDirty(e)},a=function(e){i(!1),o.add({},e)},n=function(){o.typing&&(i(!1),o.add())};return u.on("init",function(){o.add()}),u.on("BeforeExecCommand",function(e){var t=e.command;"Undo"!==t&&"Redo"!==t&&"mceRepaint"!==t&&(n(),o.beforeChange())}),u.on("ExecCommand",function(e){var t=e.command;"Undo"!==t&&"Redo"!==t&&"mceRepaint"!==t&&a(e)}),u.on("ObjectResizeStart Cut",function(){o.beforeChange()}),u.on("SaveContent ObjectResized blur",a),u.on("DragEnd",a),u.on("KeyUp",function(e){var t=e.keyCode;e.isDefaultPrevented()||((33<=t&&t<=36||37<=t&&t<=40||45===t||e.ctrlKey)&&(a(),u.nodeChanged()),46!==t&&8!==t||u.nodeChanged(),r&&o.typing&&!1===zh(Mh(u),l[0])&&(!1===u.isDirty()&&(d(!0),u.fire("change",{level:l[0],lastLevel:null})),u.fire("TypingUndo"),r=!1,u.nodeChanged()))}),u.on("KeyDown",function(e){var t=e.keyCode;if(!e.isDefaultPrevented())if(33<=t&&t<=36||37<=t&&t<=40||45===t)o.typing&&a(e);else{var n=e.ctrlKey&&!e.altKey||e.metaKey;!(t<16||20<t)||224===t||91===t||o.typing||n||(o.beforeChange(),i(!0),o.add({},e),r=!0)}}),u.on("MouseDown",function(e){o.typing&&a(e)}),u.on("input",function(e){var t;e.inputType&&("insertReplacementText"===e.inputType||"insertText"===(t=e).inputType&&null===t.data)&&a(e)}),u.addShortcut("meta+z","","Undo"),u.addShortcut("meta+y,meta+shift+z","","Redo"),u.on("AddUndo Undo Redo ClearUndos",function(e){e.isDefaultPrevented()||u.nodeChanged()}),o={data:l,typing:!1,beforeChange:function(){f()&&(s=Ec.getUndoBookmark(u.selection))},add:function(e,t){var n,r,o,i=u.settings;if(o=Mh(u),e=e||{},e=It.extend(e,o),!1===f()||u.removed)return null;if(r=l[c],u.fire("BeforeAddUndo",{level:e,lastLevel:r,originalEvent:t}).isDefaultPrevented())return null;if(r&&zh(r,e))return null;if(l[c]&&(l[c].beforeBookmark=s),i.custom_undo_redo_levels&&l.length>i.custom_undo_redo_levels){for(n=0;n<l.length-1;n++)l[n]=l[n+1];l.length--,c=l.length}e.bookmark=Ec.getUndoBookmark(u.selection),c<l.length-1&&(l.length=c+1),l.push(e),c=l.length-1;var a={level:e,lastLevel:r,originalEvent:t};return u.fire("AddUndo",a),0<c&&(d(!0),u.fire("change",a)),e},undo:function(){var e;return o.typing&&(o.add(),o.typing=!1,i(!1)),0<c&&(e=l[--c],Fh(u,e,!0),d(!0),u.fire("undo",{level:e})),e},redo:function(){var e;return c<l.length-1&&(e=l[++c],Fh(u,e,!1),d(!0),u.fire("redo",{level:e})),e},clear:function(){l=[],c=0,o.typing=!1,o.data=l,u.fire("ClearUndos")},hasUndo:function(){return 0<c||o.typing&&l[0]&&!zh(Mh(u),l[0])},hasRedo:function(){return c<l.length-1&&!o.typing},transact:function(e){return n(),o.beforeChange(),o.ignore(e),o.add()},ignore:function(e){try{t++,e()}finally{t--}},extra:function(e,t){var n,r;o.transact(e)&&(r=l[c].bookmark,n=l[c-1],Fh(u,n,!0),o.transact(t)&&(l[c-1].beforeBookmark=r))}}}var qh,Vh,Hh=function(e){return e&&/^(IMG)$/.test(e.nodeName)},jh=function(e){return e&&3===e.nodeType&&/^([\t \r\n]+|)$/.test(e.nodeValue)},$h=function(e,t,n){return"color"!==n&&"backgroundColor"!==n||(t=e.toHex(t)),"fontWeight"===n&&700===t&&(t="bold"),"fontFamily"===n&&(t=t.replace(/[\'\"]/g,"").replace(/,\s+/g,",")),""+t},Wh={isInlineBlock:Hh,moveStart:function(e,t,n){var r,o,i,a=n.startOffset,u=n.startContainer;if((n.startContainer!==n.endContainer||!Hh(n.startContainer.childNodes[n.startOffset]))&&1===u.nodeType)for(a<(i=u.childNodes).length?r=new ao(u=i[a],e.getParent(u,e.isBlock)):(r=new ao(u=i[i.length-1],e.getParent(u,e.isBlock))).next(!0),o=r.current();o;o=r.next())if(3===o.nodeType&&!jh(o))return n.setStart(o,0),void t.setRng(n)},getNonWhiteSpaceSibling:function(e,t,n){if(e)for(t=t?"nextSibling":"previousSibling",e=n?e:e[t];e;e=e[t])if(1===e.nodeType||!jh(e))return e},isTextBlock:function(e,t){return t.nodeType&&(t=t.nodeName),!!e.schema.getTextBlockElements()[t.toLowerCase()]},isValid:function(e,t,n){return e.schema.isValidChild(t,n)},isWhiteSpaceNode:jh,replaceVars:function(e,n){return"string"!=typeof e?e=e(n):n&&(e=e.replace(/%(\w+)/g,function(e,t){return n[t]||e})),e},isEq:function(e,t){return t=t||"",e=""+((e=e||"").nodeName||e),t=""+(t.nodeName||t),e.toLowerCase()===t.toLowerCase()},normalizeStyleValue:$h,getStyle:function(e,t,n){return $h(e,e.getStyle(t,n),n)},getTextDecoration:function(t,e){var n;return t.getParent(e,function(e){return(n=t.getStyle(e,"text-decoration"))&&"none"!==n}),n},getParents:function(e,t,n){return e.getParents(t,n,e.getRoot())}},Kh=Mc,Xh=Wh.getParents,Yh=Wh.isWhiteSpaceNode,Gh=Wh.isTextBlock,Jh=function(e,t){for(void 0===t&&(t=3===e.nodeType?e.length:e.childNodes.length);e&&e.hasChildNodes();)(e=e.childNodes[t])&&(t=3===e.nodeType?e.length:e.childNodes.length);return{node:e,offset:t}},Qh=function(e,t){for(var n=t;n;){if(1===n.nodeType&&e.getContentEditable(n))return"false"===e.getContentEditable(n)?n:t;n=n.parentNode}return t},Zh=function(e,t,n,r){var o,i,a=n.nodeValue;return void 0===r&&(r=e?a.length:0),e?(o=a.lastIndexOf(" ",r),-1===(o=(i=a.lastIndexOf("\xa0",r))<o?o:i)||t||o++):(o=a.indexOf(" ",r),i=a.indexOf("\xa0",r),o=-1!==o&&(-1===i||o<i)?o:i),o},ev=function(e,t,n,r,o,i){var a,u,s,c;if(3===n.nodeType){if(-1!==(s=Zh(o,i,n,r)))return{container:n,offset:s};c=n}for(a=new ao(n,e.getParent(n,e.isBlock)||t);u=a[o?"prev":"next"]();)if(3===u.nodeType){if(-1!==(s=Zh(o,i,c=u)))return{container:u,offset:s}}else if(e.isBlock(u))break;if(c)return{container:c,offset:r=o?0:c.length}},tv=function(e,t,n,r,o){var i,a,u,s;for(3===r.nodeType&&0===r.nodeValue.length&&r[o]&&(r=r[o]),i=Xh(e,r),a=0;a<i.length;a++)for(u=0;u<t.length;u++)if(!("collapsed"in(s=t[u])&&s.collapsed!==n.collapsed)&&e.is(i[a],s.selector))return i[a];return r},nv=function(t,e,n,r){var o,i=t.dom,a=i.getRoot();if(e[0].wrapper||(o=i.getParent(n,e[0].block,a)),!o){var u=i.getParent(n,"LI,TD,TH");o=i.getParent(3===n.nodeType?n.parentNode:n,function(e){return e!==a&&Gh(t,e)},u)}if(o&&e[0].wrapper&&(o=Xh(i,o,"ul,ol").reverse()[0]||o),!o)for(o=n;o[r]&&!i.isBlock(o[r])&&(o=o[r],!Wh.isEq(o,"br")););return o||n},rv=function(e,t,n,r,o,i,a){var u,s,c,l,f,d;if(u=s=a?n:o,l=a?"previousSibling":"nextSibling",f=e.getRoot(),3===u.nodeType&&!Yh(u)&&(a?0<r:i<u.nodeValue.length))return u;for(;;){if(!t[0].block_expand&&e.isBlock(s))return s;for(c=s[l];c;c=c[l])if(!Kh(c)&&!Yh(c)&&("BR"!==(d=c).nodeName||!d.getAttribute("data-mce-bogus")||d.nextSibling))return s;if(s===f||s.parentNode===f){u=s;break}s=s.parentNode}return u},ov=function(e,t,n,r){var o,i=t.startContainer,a=t.startOffset,u=t.endContainer,s=t.endOffset,c=e.dom;return 1===i.nodeType&&i.hasChildNodes()&&3===(i=ua(i,a)).nodeType&&(a=0),1===u.nodeType&&u.hasChildNodes()&&3===(u=ua(u,t.collapsed?s:s-1)).nodeType&&(s=u.nodeValue.length),i=Qh(c,i),u=Qh(c,u),(Kh(i.parentNode)||Kh(i))&&3===(i=(i=Kh(i)?i:i.parentNode).nextSibling||i).nodeType&&(a=0),(Kh(u.parentNode)||Kh(u))&&3===(u=(u=Kh(u)?u:u.parentNode).previousSibling||u).nodeType&&(s=u.length),n[0].inline&&(t.collapsed&&((o=ev(c,e.getBody(),i,a,!0,r))&&(i=o.container,a=o.offset),(o=ev(c,e.getBody(),u,s,!1,r))&&(u=o.container,s=o.offset)),u=r?u:function(e,t){var n=Jh(e,t);if(n.node){for(;n.node&&0===n.offset&&n.node.previousSibling;)n=Jh(n.node.previousSibling);n.node&&0<n.offset&&3===n.node.nodeType&&" "===n.node.nodeValue.charAt(n.offset-1)&&1<n.offset&&(e=n.node).splitText(n.offset-1)}return e}(u,s)),(n[0].inline||n[0].block_expand)&&(n[0].inline&&3===i.nodeType&&0!==a||(i=rv(c,n,i,a,u,s,!0)),n[0].inline&&3===u.nodeType&&s!==u.nodeValue.length||(u=rv(c,n,i,a,u,s,!1))),n[0].selector&&!1!==n[0].expand&&!n[0].inline&&(i=tv(c,n,t,i,"previousSibling"),u=tv(c,n,t,u,"nextSibling")),(n[0].block||n[0].selector)&&(i=nv(e,n,i,"previousSibling"),u=nv(e,n,u,"nextSibling"),n[0].block&&(c.isBlock(i)||(i=rv(c,n,i,a,u,s,!0)),c.isBlock(u)||(u=rv(c,n,i,a,u,s,!1)))),1===i.nodeType&&(a=c.nodeIndex(i),i=i.parentNode),1===u.nodeType&&(s=c.nodeIndex(u)+1,u=u.parentNode),{startContainer:i,startOffset:a,endContainer:u,endOffset:s}},iv=Wh.isEq,av=function(e,t,n){var r=e.formatter.get(n);if(r)for(var o=0;o<r.length;o++)if(!1===r[o].inherit&&e.dom.is(t,r[o].selector))return!0;return!1},uv=function(t,e,n,r){var o=t.dom.getRoot();return e!==o&&(e=t.dom.getParent(e,function(e){return!!av(t,e,n)||e.parentNode===o||!!lv(t,e,n,r,!0)}),lv(t,e,n,r))},sv=function(e,t,n){return!!iv(t,n.inline)||!!iv(t,n.block)||(n.selector?1===t.nodeType&&e.is(t,n.selector):void 0)},cv=function(e,t,n,r,o,i){var a,u,s,c=n[r];if(n.onmatch)return n.onmatch(t,n,r);if(c)if("undefined"==typeof c.length){for(a in c)if(c.hasOwnProperty(a)){if(u="attributes"===r?e.getAttrib(t,a):Wh.getStyle(e,t,a),o&&!u&&!n.exact)return;if((!o||n.exact)&&!iv(u,Wh.normalizeStyleValue(e,Wh.replaceVars(c[a],i),a)))return}}else for(s=0;s<c.length;s++)if("attributes"===r?e.getAttrib(t,c[s]):Wh.getStyle(e,t,c[s]))return n;return n},lv=function(e,t,n,r,o){var i,a,u,s,c=e.formatter.get(n),l=e.dom;if(c&&t)for(a=0;a<c.length;a++)if(i=c[a],sv(e.dom,t,i)&&cv(l,t,i,"attributes",o,r)&&cv(l,t,i,"styles",o,r)){if(s=i.classes)for(u=0;u<s.length;u++)if(!e.dom.hasClass(t,s[u]))return;return i}},fv={matchNode:lv,matchName:sv,match:function(e,t,n,r){var o;return r?uv(e,r,t,n):(r=e.selection.getNode(),!!uv(e,r,t,n)||!((o=e.selection.getStart())===r||!uv(e,o,t,n)))},matchAll:function(r,o,i){var e,a=[],u={};return e=r.selection.getStart(),r.dom.getParent(e,function(e){var t,n;for(t=0;t<o.length;t++)n=o[t],!u[n]&&lv(r,e,n,i)&&(u[n]=!0,a.push(n))},r.dom.getRoot()),a},canApply:function(e,t){var n,r,o,i,a,u=e.formatter.get(t),s=e.dom;if(u)for(n=e.selection.getStart(),r=Wh.getParents(s,n),i=u.length-1;0<=i;i--){if(!(a=u[i].selector)||u[i].defaultBlock)return!0;for(o=r.length-1;0<=o;o--)if(s.is(r[o],a))return!0}return!1},matchesUnInheritedFormatSelector:av},dv=function(e,t){return e.splitText(t)},mv=function(e){var t=e.startContainer,n=e.startOffset,r=e.endContainer,o=e.endOffset;return t===r&&Oo.isText(t)?0<n&&n<t.nodeValue.length&&(t=(r=dv(t,n)).previousSibling,n<o?(t=r=dv(r,o-=n).previousSibling,o=r.nodeValue.length,n=0):o=0):(Oo.isText(t)&&0<n&&n<t.nodeValue.length&&(t=dv(t,n),n=0),Oo.isText(r)&&0<o&&o<r.nodeValue.length&&(o=(r=dv(r,o).previousSibling).nodeValue.length)),{startContainer:t,startOffset:n,endContainer:r,endOffset:o}},pv=Ri,gv="_mce_caret",hv=function(e){return 0<function(e){for(var t=[];e;){if(3===e.nodeType&&e.nodeValue!==pv||1<e.childNodes.length)return[];1===e.nodeType&&t.push(e),e=e.firstChild}return t}(e).length},vv=function(e){var t;if(e)for(e=(t=new ao(e,e)).current();e;e=t.next())if(3===e.nodeType)return e;return null},yv=function(e){var t=Vn.fromTag("span");return lr.setAll(t,{id:gv,"data-mce-bogus":"1","data-mce-type":"format-caret"}),e&&Hu.append(t,Vn.fromText(pv)),t},bv=function(e,t,n,r){var o,i,a,u;o=t.getRng(!0),i=e.getParent(n,e.isBlock),hv(n)?(!1!==r&&(o.setStartBefore(n),o.setEndBefore(n)),e.remove(n)):((u=vv(n))&&u.nodeValue.charAt(0)===pv&&u.deleteData(0,1),a=u,o.startContainer===a&&0<o.startOffset&&o.setStart(a,o.startOffset-1),o.endContainer===a&&0<o.endOffset&&o.setEnd(a,o.endOffset-1),e.remove(n,!0)),i&&e.isEmpty(i)&&Kc(Vn.fromDom(i)),t.setRng(o)},Cv=function(e,t,n,r,o){if(r)bv(t,n,r,o);else if(!(r=Tc(e,n.getStart())))for(;r=t.get(gv);)bv(t,n,r,!1)},xv=function(e,t,n){var r=e.dom,o=r.getParent(n,da.curry(Wh.isTextBlock,e));o&&r.isEmpty(o)?n.parentNode.replaceChild(t,n):(Wc(Vn.fromDom(n)),r.isEmpty(n)?n.parentNode.replaceChild(t,n):r.insertAfter(t,n))},wv=function(e,t){return e.appendChild(t),t},Nv=function(e,t){var n=H.foldr(e,function(e,t){return wv(e,t.cloneNode(!1))},t);return wv(n,n.ownerDocument.createTextNode(pv))},Ev=function(e){var i=e.dom,a=e.selection,u=e.getBody();e.on("mouseup keydown",function(e){var t,n,r,o;t=u,n=i,r=a,o=e.keyCode,Cv(t,n,r,null,!1),8===o&&r.isCollapsed()&&r.getStart().innerHTML===pv&&Cv(t,n,r,Tc(t,r.getStart())),37!==o&&39!==o||Cv(t,n,r,Tc(t,r.getStart()))})},Sv=function(e,t){return e.schema.getTextInlineElements().hasOwnProperty(Zn.name(t))&&!kc(t.dom())&&!Oo.isBogus(t.dom())},kv={},Tv=Bt.filter,Av=Bt.each;Vh=function(e){var t,n,r=e.selection.getRng();t=Oo.matchNodeNames("pre"),r.collapsed||(n=e.selection.getSelectedBlocks(),Av(Tv(Tv(n,t),function(e){return t(e.previousSibling)&&-1!==Bt.indexOf(n,e.previousSibling)}),function(e){var t,n;t=e.previousSibling,tn(n=e).remove(),tn(t).append("<br><br>").append(n.childNodes)}))},kv[qh="pre"]||(kv[qh]=[]),kv[qh].push(Vh);var Rv=function(e,t){Av(kv[e],function(e){e(t)})},_v=It.each,Bv=function(e,t,o){var n,r,i,a,u,s,c,l=t.startContainer,f=t.startOffset,d=t.endContainer,m=t.endOffset;if(0<(c=e.select("td[data-mce-selected],th[data-mce-selected]")).length)_v(c,function(e){o([e])});else{var p,g,h,v=function(e){var t;return 3===(t=e[0]).nodeType&&t===l&&f>=t.nodeValue.length&&e.splice(0,1),t=e[e.length-1],0===m&&0<e.length&&t===d&&3===t.nodeType&&e.splice(e.length-1,1),e},y=function(e,t,n){for(var r=[];e&&e!==n;e=e[t])r.push(e);return r},b=function(e,t){do{if(e.parentNode===t)return e;e=e.parentNode}while(e)},C=function(e,t,n){var r=n?"nextSibling":"previousSibling";for(u=(a=e).parentNode;a&&a!==t;a=u)u=a.parentNode,(s=y(a===e?a:a[r],r)).length&&(n||s.reverse(),o(v(s)))};if(1===l.nodeType&&l.hasChildNodes()&&(l=l.childNodes[f]),1===d.nodeType&&d.hasChildNodes()&&(g=m,h=(p=d).childNodes,--g>h.length-1?g=h.length-1:g<0&&(g=0),d=h[g]||p),l===d)return o(v([l]));for(n=e.findCommonAncestor(l,d),a=l;a;a=a.parentNode){if(a===d)return C(l,n,!0);if(a===n)break}for(a=d;a;a=a.parentNode){if(a===l)return C(d,n);if(a===n)break}r=b(l,n)||l,i=b(d,n)||d,C(l,r,!0),(s=y(r===l?r:r.nextSibling,"nextSibling",i===d?i.nextSibling:i)).length&&o(v(s)),C(d,i)}},Dv=/^(src|href|style)$/,Ov=It.each,Pv=Wh.isEq,Lv=function(e){return/^(TH|TD)$/.test(e.nodeName)},Iv=function(e,t,n){var r,o,i;return r=t[n?"startContainer":"endContainer"],o=t[n?"startOffset":"endOffset"],Oo.isElement(r)&&(i=r.childNodes.length-1,!n&&o&&o--,r=r.childNodes[i<o?i:o]),Oo.isText(r)&&n&&o>=r.nodeValue.length&&(r=new ao(r,e.getBody()).next()||r),Oo.isText(r)&&!n&&0===o&&(r=new ao(r,e.getBody()).prev()||r),r},Mv=function(e,t,n,r){var o=e.create(n,r);return t.parentNode.insertBefore(o,t),o.appendChild(t),o},Fv=function(e,t,n,r){return!(t=Wh.getNonWhiteSpaceSibling(t,n,r))||"BR"===t.nodeName||e.isBlock(t)},zv=function(e,n,r,o,i){var t,a,u,s,c,l,f,d,m,p,g,h,v,y,b=e.dom;if(c=b,!(Pv(l=o,(f=n).inline)||Pv(l,f.block)||(f.selector?Oo.isElement(l)&&c.is(l,f.selector):void 0)||(s=o,n.links&&"A"===s.tagName)))return!1;if("all"!==n.remove)for(Ov(n.styles,function(e,t){e=Wh.normalizeStyleValue(b,Wh.replaceVars(e,r),t),"number"==typeof t&&(t=e,i=0),(n.remove_similar||!i||Pv(Wh.getStyle(b,i,t),e))&&b.setStyle(o,t,""),u=1}),u&&""===b.getAttrib(o,"style")&&(o.removeAttribute("style"),o.removeAttribute("data-mce-style")),Ov(n.attributes,function(e,t){var n;if(e=Wh.replaceVars(e,r),"number"==typeof t&&(t=e,i=0),!i||Pv(b.getAttrib(i,t),e)){if("class"===t&&(e=b.getAttrib(o,t))&&(n="",Ov(e.split(/\s+/),function(e){/mce\-\w+/.test(e)&&(n+=(n?" ":"")+e)}),n))return void b.setAttrib(o,t,n);"class"===t&&o.removeAttribute("className"),Dv.test(t)&&o.removeAttribute("data-mce-"+t),o.removeAttribute(t)}}),Ov(n.classes,function(e){e=Wh.replaceVars(e,r),i&&!b.hasClass(i,e)||b.removeClass(o,e)}),a=b.getAttribs(o),t=0;t<a.length;t++){var C=a[t].nodeName;if(0!==C.indexOf("_")&&0!==C.indexOf("data-"))return!1}return"none"!==n.remove?(d=e,p=n,h=(m=o).parentNode,v=d.dom,y=d.settings.forced_root_block,p.block&&(y?h===v.getRoot()&&(p.list_block&&Pv(m,p.list_block)||Ov(It.grep(m.childNodes),function(e){Wh.isValid(d,y,e.nodeName.toLowerCase())?g?g.appendChild(e):(g=Mv(v,e,y),v.setAttribs(g,d.settings.forced_root_block_attrs)):g=0})):v.isBlock(m)&&!v.isBlock(h)&&(Fv(v,m,!1)||Fv(v,m.firstChild,!0,1)||m.insertBefore(v.create("br"),m.firstChild),Fv(v,m,!0)||Fv(v,m.lastChild,!1,1)||m.appendChild(v.create("br")))),p.selector&&p.inline&&!Pv(p.inline,m)||v.remove(m,1),!0):void 0},Uv=zv,qv=function(s,c,l,e,f){var t,n,d=s.formatter.get(c),m=d[0],a=!0,u=s.dom,r=s.selection,o=function(e){var n,t,r,o,i,a,u=(n=s,t=e,r=c,o=l,i=f,Ov(Wh.getParents(n.dom,t.parentNode).reverse(),function(e){var t;a||"_start"===e.id||"_end"===e.id||(t=fv.matchNode(n,e,r,o,i))&&!1!==t.split&&(a=e)}),a);return function(e,t,n,r,o,i,a,u){var s,c,l,f,d,m,p=e.dom;if(n){for(m=n.parentNode,s=r.parentNode;s&&s!==m;s=s.parentNode){for(c=p.clone(s,!1),d=0;d<t.length;d++)if(zv(e,t[d],u,c,c)){c=0;break}c&&(l&&c.appendChild(l),f||(f=c),l=c)}!i||a.mixed&&p.isBlock(n)||(r=p.split(n,r)),l&&(o.parentNode.insertBefore(l,o),f.appendChild(o))}return r}(s,d,u,e,e,!0,m,l)},p=function(e){var t,n,r,o,i;if(Oo.isElement(e)&&u.getContentEditable(e)&&(o=a,a="true"===u.getContentEditable(e),i=!0),t=It.grep(e.childNodes),a&&!i)for(n=0,r=d.length;n<r&&!zv(s,d[n],l,e,e);n++);if(m.deep&&t.length){for(n=0,r=t.length;n<r;n++)p(t[n]);i&&(a=o)}},i=function(e){var t=u.get(e?"_start":"_end"),n=t[e?"firstChild":"lastChild"];return Mc(n)&&(n=n[e?"firstChild":"lastChild"]),Oo.isText(n)&&0===n.data.length&&(n=e?t.previousSibling||t.nextSibling:t.nextSibling||t.previousSibling),u.remove(t,!0),n},g=function(e){var t,n,r=e.commonAncestorContainer;if(e=ov(s,e,d,!0),m.split){if((t=Iv(s,e,!0))!==(n=Iv(s,e))){if(/^(TR|TH|TD)$/.test(t.nodeName)&&t.firstChild&&(t="TR"===t.nodeName?t.firstChild.firstChild||t:t.firstChild||t),r&&/^T(HEAD|BODY|FOOT|R)$/.test(r.nodeName)&&Lv(n)&&n.firstChild&&(n=n.firstChild||n),u.isChildOf(t,n)&&t!==n&&!u.isBlock(n)&&!Lv(t)&&!Lv(n))return t=Mv(u,t,"span",{id:"_start","data-mce-type":"bookmark"}),o(t),void(t=i(!0));t=Mv(u,t,"span",{id:"_start","data-mce-type":"bookmark"}),n=Mv(u,n,"span",{id:"_end","data-mce-type":"bookmark"}),o(t),o(n),t=i(!0),n=i()}else t=n=o(t);e.startContainer=t.parentNode?t.parentNode:t,e.startOffset=u.nodeIndex(t),e.endContainer=n.parentNode?n.parentNode:n,e.endOffset=u.nodeIndex(n)+1}Bv(u,e,function(e){Ov(e,function(e){p(e),Oo.isElement(e)&&"underline"===s.dom.getStyle(e,"text-decoration")&&e.parentNode&&"underline"===Wh.getTextDecoration(u,e.parentNode)&&zv(s,{deep:!1,exact:!0,inline:"span",styles:{textDecoration:"underline"}},null,e)})})};if(e)e.nodeType?((n=u.createRng()).setStartBefore(e),n.setEndAfter(e),g(n)):g(e);else if("false"!==u.getContentEditable(r.getNode()))r.isCollapsed()&&m.inline&&!u.select("td[data-mce-selected],th[data-mce-selected]").length?function(e,t,n,r){var o,i,a,u,s,c,l,f=e.dom,d=e.selection,m=[],p=d.getRng();for(o=p.startContainer,i=p.startOffset,3===(s=o).nodeType&&(i!==o.nodeValue.length&&(u=!0),s=s.parentNode);s;){if(fv.matchNode(e,s,t,n,r)){c=s;break}s.nextSibling&&(u=!0),m.push(s),s=s.parentNode}if(c)if(u){a=d.getBookmark(),p.collapse(!0);var g=ov(e,p,e.formatter.get(t),!0);g=mv(g),e.formatter.remove(t,n,g),d.moveToBookmark(a)}else{l=Tc(e.getBody(),c);var h=yv(!1).dom(),v=Nv(m,h);xv(e,h,l||c),bv(f,d,l,!1),d.setCursorLocation(v,1),f.isEmpty(c)&&f.remove(c)}}(s,c,l,f):(t=Ec.getPersistentBookmark(s.selection,!0),g(r.getRng()),r.moveToBookmark(t),m.inline&&fv.match(s,c,l,r.getStart())&&Wh.moveStart(u,r,r.getRng()),s.nodeChanged());else{e=r.getNode();for(var h=0,v=d.length;h<v&&(!d[h].ceFalseOverride||!zv(s,d[h],l,e,e));h++);}},Vv=It.each,Hv=function(e){return e&&1===e.nodeType&&!Mc(e)&&!kc(e)&&!Oo.isBogus(e)},jv=function(e,t){var n;for(n=e;n;n=n[t]){if(3===n.nodeType&&0!==n.nodeValue.length)return e;if(1===n.nodeType&&!Mc(n))return n}return e},$v=function(e,t,n){var r,o,i=new zc(e);if(t&&n&&(t=jv(t,"previousSibling"),n=jv(n,"nextSibling"),i.compare(t,n))){for(r=t.nextSibling;r&&r!==n;)r=(o=r).nextSibling,t.appendChild(o);return e.remove(n),It.each(It.grep(n.childNodes),function(e){t.appendChild(e)}),t}return n},Wv=function(e,t,n){Vv(e.childNodes,function(e){Hv(e)&&(t(e)&&n(e),e.hasChildNodes()&&Wv(e,t,n))})},Kv=function(n,e){return V.curry(function(e,t){return!(!t||!Wh.getStyle(n,t,e))},e)},Xv=function(r,e,t){return V.curry(function(e,t,n){r.setStyle(n,e,t),""===n.getAttribute("style")&&n.removeAttribute("style"),Yv(r,n)},e,t)},Yv=function(e,t){"SPAN"===t.nodeName&&0===e.getAttribs(t).length&&e.remove(t,!0)},Gv=function(e,t){var n;1===t.nodeType&&t.parentNode&&1===t.parentNode.nodeType&&(n=Wh.getTextDecoration(e,t.parentNode),e.getStyle(t,"color")&&n?e.setStyle(t,"text-decoration",n):e.getStyle(t,"text-decoration")===n&&e.setStyle(t,"text-decoration",null))},Jv=function(n,e,r,o){Vv(e,function(t){Vv(n.dom.select(t.inline,o),function(e){Hv(e)&&Uv(n,t,r,e,t.exact?e:null)}),function(r,e,t){if(e.clear_child_styles){var n=e.links?"*:not(a)":"*";Vv(r.select(n,t),function(n){Hv(n)&&Vv(e.styles,function(e,t){r.setStyle(n,t,"")})})}}(n.dom,t,o)})},Qv=function(e,t,n,r){(t.styles.color||t.styles.textDecoration)&&(It.walk(r,V.curry(Gv,e),"childNodes"),Gv(e,r))},Zv=function(e,t,n,r){t.styles&&t.styles.backgroundColor&&Wv(r,Kv(e,"fontSize"),Xv(e,"backgroundColor",Wh.replaceVars(t.styles.backgroundColor,n)))},ey=function(e,t,n,r){"sub"!==t.inline&&"sup"!==t.inline||(Wv(r,Kv(e,"fontSize"),Xv(e,"fontSize","")),e.remove(e.select("sup"===t.inline?"sub":"sup",r),!0))},ty=function(e,t,n,r){r&&!1!==t.merge_siblings&&(r=$v(e,Wh.getNonWhiteSpaceSibling(r),r),r=$v(e,r,Wh.getNonWhiteSpaceSibling(r,!0)))},ny=function(t,n,r,o,i){fv.matchNode(t,i.parentNode,r,o)&&Uv(t,n,o,i)||n.merge_with_parents&&t.dom.getParent(i.parentNode,function(e){if(fv.matchNode(t,e,r,o))return Uv(t,n,o,i),!0})},ry=It.each,oy=function(p,g,h,r){var e,t,v=p.formatter.get(g),y=v[0],o=!r&&p.selection.isCollapsed(),i=p.dom,n=p.selection,b=function(n,e){if(e=e||y,n){if(e.onformat&&e.onformat(n,e,h,r),ry(e.styles,function(e,t){i.setStyle(n,t,Wh.replaceVars(e,h))}),e.styles){var t=i.getAttrib(n,"style");t&&n.setAttribute("data-mce-style",t)}ry(e.attributes,function(e,t){i.setAttrib(n,t,Wh.replaceVars(e,h))}),ry(e.classes,function(e){e=Wh.replaceVars(e,h),i.hasClass(n,e)||i.addClass(n,e)})}},C=function(e,t){var n=!1;return!!y.selector&&(ry(e,function(e){if(!("collapsed"in e&&e.collapsed!==o))return i.is(t,e.selector)&&!kc(t)?(b(t,e),!(n=!0)):void 0}),n)},a=function(s,e,t,c){var l,f,d=[],m=!0;l=y.inline||y.block,f=s.create(l),b(f),Bv(s,e,function(e){var a,u=function(e){var t,n,r,o;if(o=m,t=e.nodeName.toLowerCase(),n=e.parentNode.nodeName.toLowerCase(),1===e.nodeType&&s.getContentEditable(e)&&(o=m,m="true"===s.getContentEditable(e),r=!0),Wh.isEq(t,"br"))return a=0,void(y.block&&s.remove(e));if(y.wrapper&&fv.matchNode(p,e,g,h))a=0;else{if(m&&!r&&y.block&&!y.wrapper&&Wh.isTextBlock(p,t)&&Wh.isValid(p,n,l))return e=s.rename(e,l),b(e),d.push(e),void(a=0);if(y.selector){var i=C(v,e);if(!y.inline||i)return void(a=0)}!m||r||!Wh.isValid(p,l,t)||!Wh.isValid(p,n,l)||!c&&3===e.nodeType&&1===e.nodeValue.length&&65279===e.nodeValue.charCodeAt(0)||kc(e)||y.inline&&s.isBlock(e)?(a=0,ry(It.grep(e.childNodes),u),r&&(m=o),a=0):(a||(a=s.clone(f,!1),e.parentNode.insertBefore(a,e),d.push(a)),a.appendChild(e))}};ry(e,u)}),!0===y.links&&ry(d,function(e){var t=function(e){"A"===e.nodeName&&b(e,y),ry(It.grep(e.childNodes),t)};t(e)}),ry(d,function(e){var t,n,r,o,i,a=function(e){var n=!1;return ry(e.childNodes,function(e){if((t=e)&&1===t.nodeType&&!Mc(t)&&!kc(t)&&!Oo.isBogus(t))return n=e,!1;var t}),n};n=0,ry(e.childNodes,function(e){Wh.isWhiteSpaceNode(e)||Mc(e)||n++}),t=n,!(1<d.length)&&s.isBlock(e)||0!==t?(y.inline||y.wrapper)&&(y.exact||1!==t||((o=a(r=e))&&!Mc(o)&&fv.matchName(s,o,y)&&(i=s.clone(o,!1),b(i),s.replace(i,r,!0),s.remove(o,1)),e=i||r),Jv(p,v,h,e),ny(p,y,g,h,e),Zv(s,y,h,e),ey(s,y,h,e),ty(s,y,h,e)):s.remove(e,1)})};if("false"!==i.getContentEditable(n.getNode())){if(y){if(r)r.nodeType?C(v,r)||((t=i.createRng()).setStartBefore(r),t.setEndAfter(r),a(i,ov(p,t,v),0,!0)):a(i,r,0,!0);else if(o&&y.inline&&!i.select("td[data-mce-selected],th[data-mce-selected]").length)!function(e,t,n){var r,o,i,a,u,s,c=e.selection;a=(r=c.getRng(!0)).startOffset,s=r.startContainer.nodeValue,(o=Tc(e.getBody(),c.getStart()))&&(i=vv(o));var l,f,d=/[^\s\u00a0\u00ad\u200b\ufeff]/;s&&0<a&&a<s.length&&d.test(s.charAt(a))&&d.test(s.charAt(a-1))?(u=c.getBookmark(),r.collapse(!0),r=ov(e,r,e.formatter.get(t)),r=mv(r),e.formatter.apply(t,n,r),c.moveToBookmark(u)):(o&&i.nodeValue===pv||(l=e.getDoc(),f=yv(!0).dom(),i=(o=l.importNode(f,!0)).firstChild,r.insertNode(o),a=1),e.formatter.apply(t,n,o),c.setCursorLocation(i,a))}(p,g,h);else{var u=p.selection.getNode();p.settings.forced_root_block||!v[0].defaultBlock||i.getParent(u,i.isBlock)||oy(p,v[0].defaultBlock),p.selection.setRng(Zc(p.selection.getRng())),e=Ec.getPersistentBookmark(p.selection,!0),a(i,ov(p,n.getRng(),v)),y.styles&&Qv(i,y,h,u),n.moveToBookmark(e),Wh.moveStart(i,n,n.getRng()),p.nodeChanged()}Rv(g,p)}}else{r=n.getNode();for(var s=0,c=v.length;s<c;s++)if(v[s].ceFalseOverride&&i.is(r,v[s].selector))return void b(r,v[s])}},iy={applyFormat:oy},ay=It.each,uy=function(e,t,n,r,o){var i,a,u,s,c,l,f,d;null===t.get()&&(a=e,u={},(i=t).set({}),a.on("NodeChange",function(n){var r=Wh.getParents(a.dom,n.element),o={};r=It.grep(r,function(e){return 1===e.nodeType&&!e.getAttribute("data-mce-bogus")}),ay(i.get(),function(e,n){ay(r,function(t){return a.formatter.matchNode(t,n,{},e.similar)?(u[n]||(ay(e,function(e){e(!0,{node:t,format:n,parents:r})}),u[n]=e),o[n]=e,!1):!fv.matchesUnInheritedFormatSelector(a,t,n)&&void 0})}),ay(u,function(e,t){o[t]||(delete u[t],ay(e,function(e){e(!1,{node:n.element,format:t,parents:r})}))})})),c=n,l=r,f=o,d=(s=t).get(),ay(c.split(","),function(e){d[e]||(d[e]=[],d[e].similar=f),d[e].push(l)}),s.set(d)},sy={get:function(r){var t={valigntop:[{selector:"td,th",styles:{verticalAlign:"top"}}],valignmiddle:[{selector:"td,th",styles:{verticalAlign:"middle"}}],valignbottom:[{selector:"td,th",styles:{verticalAlign:"bottom"}}],alignleft:[{selector:"figure.image",collapsed:!1,classes:"align-left",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"left"},inherit:!1,preview:!1,defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"left"},preview:"font-family font-size"}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"center"},inherit:!1,preview:"font-family font-size",defaultBlock:"div"},{selector:"figure.image",collapsed:!1,classes:"align-center",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"img",collapsed:!1,styles:{display:"block",marginLeft:"auto",marginRight:"auto"},preview:!1},{selector:"table",collapsed:!1,styles:{marginLeft:"auto",marginRight:"auto"},preview:"font-family font-size"}],alignright:[{selector:"figure.image",collapsed:!1,classes:"align-right",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"right"},inherit:!1,preview:"font-family font-size",defaultBlock:"div"},{selector:"img,table",collapsed:!1,styles:{"float":"right"},preview:"font-family font-size"}],alignjustify:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"justify"},inherit:!1,defaultBlock:"div",preview:"font-family font-size"}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:!0},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:!0},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0},fontname:{inline:"span",toggle:!1,styles:{fontFamily:"%value"},clear_child_styles:!0},fontsize:{inline:"span",toggle:!1,styles:{fontSize:"%value"},clear_child_styles:!0},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},code:{inline:"code"},link:{inline:"a",selector:"a",remove:"all",split:!0,deep:!0,onmatch:function(){return!0},onformat:function(n,e,t){It.each(t,function(e,t){r.setAttrib(n,t,e)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins",remove:"all",split:!0,expand:!1,block_expand:!0,deep:!0},{selector:"span",attributes:["style","class"],remove:"empty",split:!0,expand:!1,deep:!0},{selector:"*",attributes:["style","class"],split:!1,expand:!1,deep:!0}]};return It.each("p h1 h2 h3 h4 h5 h6 div address pre div dt dd samp".split(/\s/),function(e){t[e]={block:e,remove:"all"}}),t}},cy=It.each,ly=vi.DOM,fy=function(e,t){var n,o,r,m=t&&t.schema||oi({}),p=function(e){var t,n,r;return o="string"==typeof e?{name:e,classes:[],attrs:{}}:e,t=ly.create(o.name),n=t,(r=o).classes.length&&ly.addClass(n,r.classes.join(" ")),ly.setAttribs(n,r.attrs),t},g=function(n,e,t){var r,o,i,a,u,s,c,l,f=0<e.length&&e[0],d=f&&f.name;if(u=d,s="string"!=typeof(a=n)?a.nodeName.toLowerCase():a,c=m.getElementRule(s),i=!(!(l=c&&c.parentsRequired)||!l.length)&&(u&&-1!==It.inArray(l,u)?u:l[0]))d===i?(o=e[0],e=e.slice(1)):o=i;else if(f)o=e[0],e=e.slice(1);else if(!t)return n;return o&&(r=p(o)).appendChild(n),t&&(r||(r=ly.create("div")).appendChild(n),It.each(t,function(e){var t=p(e);r.insertBefore(t,n)})),g(r,e,o&&o.siblings)};return e&&e.length?(o=e[0],n=p(o),(r=ly.create("div")).appendChild(g(n,e.slice(1),o.siblings)),r):""},dy=function(e){var t,a={classes:[],attrs:{}};return"*"!==(e=a.selector=It.trim(e))&&(t=e.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g,function(e,t,n,r,o){switch(t){case"#":a.attrs.id=n;break;case".":a.classes.push(n);break;case":":-1!==It.inArray("checked disabled enabled read-only required".split(" "),n)&&(a.attrs[n]=n)}if("["===r){var i=o.match(/([\w\-]+)(?:\=\"([^\"]+))?/);i&&(a.attrs[i[1]]=i[2])}return""})),a.name=t||"div",a},my=function(e){return e&&"string"==typeof e?(e=(e=e.split(/\s*,\s*/)[0]).replace(/\s*(~\+|~|\+|>)\s*/g,"$1"),It.map(e.split(/(?:>|\s+(?![^\[\]]+\]))/),function(e){var t=It.map(e.split(/(?:~\+|~|\+)/),dy),n=t.pop();return t.length&&(n.siblings=t),n}).reverse()):[]},py=function(n,e){var t,r,o,i,a,u,s="";if(!1===(u=n.settings.preview_styles))return"";"string"!=typeof u&&(u="font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow");var c=function(e){return e.replace(/%(\w+)/g,"")};if("string"==typeof e){if(!(e=n.formatter.get(e)))return;e=e[0]}return"preview"in e&&!1===(u=e.preview)?"":(t=e.block||e.inline||"span",(i=my(e.selector)).length?(i[0].name||(i[0].name=t),t=e.selector,r=fy(i,n)):r=fy([t],n),o=ly.select(t,r)[0]||r.firstChild,cy(e.styles,function(e,t){(e=c(e))&&ly.setStyle(o,t,e)}),cy(e.attributes,function(e,t){(e=c(e))&&ly.setAttrib(o,t,e)}),cy(e.classes,function(e){e=c(e),ly.hasClass(o,e)||ly.addClass(o,e)}),n.fire("PreviewFormats"),ly.setStyles(r,{position:"absolute",left:-65535}),n.getBody().appendChild(r),a=ly.getStyle(n.getBody(),"fontSize",!0),a=/px$/.test(a)?parseInt(a,10):0,cy(u.split(" "),function(e){var t=ly.getStyle(o,e,!0);if(!("background-color"===e&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(t)&&(t=ly.getStyle(n.getBody(),e,!0),"#ffffff"===ly.toHex(t).toLowerCase())||"color"===e&&"#000000"===ly.toHex(t).toLowerCase())){if("font-size"===e&&/em|%$/.test(t)){if(0===a)return;t=parseFloat(t)/(/%$/.test(t)?100:1)*a+"px"}"border"===e&&t&&(s+="padding:0 2px;"),s+=e+":"+t+";"}}),n.fire("AfterPreviewFormats"),ly.remove(r),s)},gy=function(e,t,n,r,o){var i=t.get(n);!fv.match(e,n,r,o)||"toggle"in i[0]&&!i[0].toggle?iy.applyFormat(e,n,r,o):qv(e,n,r,o)},hy=function(e){e.addShortcut("meta+b","","Bold"),e.addShortcut("meta+i","","Italic"),e.addShortcut("meta+u","","Underline");for(var t=1;t<=6;t++)e.addShortcut("access+"+t,"",["FormatBlock",!1,"h"+t]);e.addShortcut("access+7","",["FormatBlock",!1,"p"]),e.addShortcut("access+8","",["FormatBlock",!1,"div"]),e.addShortcut("access+9","",["FormatBlock",!1,"address"])};function vy(e){var t,n,r,o=(t=e,n={},(r=function(e,t){e&&("string"!=typeof e?It.each(e,function(e,t){r(t,e)}):(t=t.length?t:[t],It.each(t,function(e){"undefined"==typeof e.deep&&(e.deep=!e.selector),"undefined"==typeof e.split&&(e.split=!e.selector||e.inline),"undefined"==typeof e.remove&&e.selector&&!e.inline&&(e.remove="none"),e.selector&&e.inline&&(e.mixed=!0,e.block_expand=!0),"string"==typeof e.classes&&(e.classes=e.classes.split(/\s+/))}),n[e]=t))})(sy.get(t.dom)),r(t.settings.formats),{get:function(e){return e?n[e]:n},register:r,unregister:function(e){return e&&n[e]&&delete n[e],n}}),i=ns(null);return hy(e),Ev(e),{get:o.get,register:o.register,unregister:o.unregister,apply:V.curry(iy.applyFormat,e),remove:V.curry(qv,e),toggle:V.curry(gy,e,o),match:V.curry(fv.match,e),matchAll:V.curry(fv.matchAll,e),matchNode:V.curry(fv.matchNode,e),canApply:V.curry(fv.canApply,e),formatChanged:V.curry(uy,e,i),getCssText:V.curry(py,e)}}var yy=function(a){return function(){for(var e=new Array(arguments.length),t=0;t<e.length;t++)e[t]=arguments[t];if(0===e.length)throw new Error("Can't merge zero objects");for(var n={},r=0;r<e.length;r++){var o=e[r];for(var i in o)o.hasOwnProperty(i)&&(n[i]=a(n[i],o[i]))}return n}},by=yy(function(e,t){return k.isObject(e)&&k.isObject(t)?by(e,t):t}),Cy=yy(function(e,t){return t}),xy={deepMerge:by,merge:Cy},wy={register:function(t,s,c){t.addAttributeFilter("data-mce-tabindex",function(e,t){for(var n,r=e.length;r--;)(n=e[r]).attr("tabindex",n.attributes.map["data-mce-tabindex"]),n.attr(t,null)}),t.addAttributeFilter("src,href,style",function(e,t){for(var n,r,o=e.length,i="data-mce-"+t,a=s.url_converter,u=s.url_converter_scope;o--;)(r=(n=e[o]).attributes.map[i])!==undefined?(n.attr(t,0<r.length?r:null),n.attr(i,null)):(r=n.attributes.map[t],"style"===t?r=c.serializeStyle(c.parseStyle(r),n.name):a&&(r=a.call(u,r,t,n.name)),n.attr(t,0<r.length?r:null))}),t.addAttributeFilter("class",function(e){for(var t,n,r=e.length;r--;)(n=(t=e[r]).attr("class"))&&(n=t.attr("class").replace(/(?:^|\s)mce-item-\w+(?!\S)/g,""),t.attr("class",0<n.length?n:null))}),t.addAttributeFilter("data-mce-type",function(e,t,n){for(var r,o=e.length;o--;)"bookmark"!==(r=e[o]).attributes.map["data-mce-type"]||n.cleanup||r.remove()}),t.addNodeFilter("noscript",function(e){for(var t,n=e.length;n--;)(t=e[n].firstChild)&&(t.value=Ko.decode(t.value))}),t.addNodeFilter("script,style",function(e,t){for(var n,r,o,i=e.length,a=function(e){return e.replace(/(<!--\[CDATA\[|\]\]-->)/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi,"").replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")};i--;)r=(n=e[i]).firstChild?n.firstChild.value:"","script"===t?((o=n.attr("type"))&&n.attr("type","mce-no/type"===o?null:o.replace(/^mce\-/,"")),"xhtml"===s.element_format&&0<r.length&&(n.firstChild.value="// <![CDATA[\n"+a(r)+"\n// ]]>")):"xhtml"===s.element_format&&0<r.length&&(n.firstChild.value="\x3c!--\n"+a(r)+"\n--\x3e")}),t.addNodeFilter("#comment",function(e){for(var t,n=e.length;n--;)0===(t=e[n]).value.indexOf("[CDATA[")?(t.name="#cdata",t.type=4,t.value=t.value.replace(/^\[CDATA\[|\]\]$/g,"")):0===t.value.indexOf("mce:protected ")&&(t.name="#text",t.type=3,t.raw=!0,t.value=unescape(t.value).substr(14))}),t.addNodeFilter("xml:namespace,input",function(e,t){for(var n,r=e.length;r--;)7===(n=e[r]).type?n.remove():1===n.type&&("input"!==t||"type"in n.attributes.map||n.attr("type","text"))}),t.addAttributeFilter("data-mce-type",function(e){H.each(e,function(e){"format-caret"===e.attr("data-mce-type")&&(e.isEmpty(t.schema.getNonEmptyElements())?e.remove():e.unwrap())})}),t.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style,data-mce-selected,data-mce-expando,data-mce-type,data-mce-resize",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)})},trimTrailingBr:function(e){var t,n,r=function(e){return e&&"br"===e.name};r(t=e.lastChild)&&r(n=t.prev)&&(t.remove(),n.remove())}},Ny={process:function(e,t,n){return f=n,(l=e)&&l.hasEventListeners("PreProcess")&&!f.no_events?(o=t,i=n,c=(r=e).dom,o=o.cloneNode(!0),(a=document.implementation).createHTMLDocument&&(u=a.createHTMLDocument(""),It.each("BODY"===o.nodeName?o.childNodes:[o],function(e){u.body.appendChild(u.importNode(e,!0))}),o="BODY"!==o.nodeName?u.body.firstChild:u.body,s=c.doc,c.doc=u),cp(r,xy.merge(i,{node:o})),s&&(c.doc=s),o):t;var r,o,i,a,u,s,c,l,f}},Ey=function(e,u,s){e.addNodeFilter("font",function(e){H.each(e,function(e){var t,n,r=u.parse(e.attr("style")),o=e.attr("color"),i=e.attr("face"),a=e.attr("size");o&&(r.color=o),i&&(r["font-family"]=i),a&&(r["font-size"]=s[parseInt(e.attr("size"),10)-1]),e.name="span",e.attr("style",u.serialize(r)),t=e,n=["color","face","size"],H.each(n,function(e){t.attr(e,null)})})})},Sy=function(e,t){var n,r=ai();t.convert_fonts_to_spans&&Ey(e,r,It.explode(t.font_size_legacy_values)),n=r,e.addNodeFilter("strike",function(e){H.each(e,function(e){var t=n.parse(e.attr("style"));t["text-decoration"]="line-through",e.name="span",e.attr("style",n.serialize(t))})})},ky={register:function(e,t){t.inline_styles&&Sy(e,t)}},Ty=/^[ \t\r\n]*$/,Ay={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11},Ry=function(e,t,n){var r,o,i=n?"lastChild":"firstChild",a=n?"prev":"next";if(e[i])return e[i];if(e!==t){if(r=e[a])return r;for(o=e.parent;o&&o!==t;o=o.parent)if(r=o[a])return r}},_y=function(){function a(e,t){this.name=e,1===(this.type=t)&&(this.attributes=[],this.attributes.map={})}return a.create=function(e,t){var n,r;if(n=new a(e,Ay[e]||1),t)for(r in t)n.attr(r,t[r]);return n},a.prototype.replace=function(e){return e.parent&&e.remove(),this.insert(e,this),this.remove(),this},a.prototype.attr=function(e,t){var n,r;if("string"!=typeof e){for(r in e)this.attr(r,e[r]);return this}if(n=this.attributes){if(t!==undefined){if(null===t){if(e in n.map)for(delete n.map[e],r=n.length;r--;)if(n[r].name===e)return n=n.splice(r,1),this;return this}if(e in n.map){for(r=n.length;r--;)if(n[r].name===e){n[r].value=t;break}}else n.push({name:e,value:t});return n.map[e]=t,this}return n.map[e]}},a.prototype.clone=function(){var e,t,n,r,o,i=new a(this.name,this.type);if(n=this.attributes){for((o=[]).map={},e=0,t=n.length;e<t;e++)"id"!==(r=n[e]).name&&(o[o.length]={name:r.name,value:r.value},o.map[r.name]=r.value);i.attributes=o}return i.value=this.value,i.shortEnded=this.shortEnded,i},a.prototype.wrap=function(e){return this.parent.insert(e,this),e.append(this),this},a.prototype.unwrap=function(){var e,t;for(e=this.firstChild;e;)t=e.next,this.insert(e,this,!0),e=t;this.remove()},a.prototype.remove=function(){var e=this.parent,t=this.next,n=this.prev;return e&&(e.firstChild===this?(e.firstChild=t)&&(t.prev=null):n.next=t,e.lastChild===this?(e.lastChild=n)&&(n.next=null):t.prev=n,this.parent=this.next=this.prev=null),this},a.prototype.append=function(e){var t;return e.parent&&e.remove(),(t=this.lastChild)?((t.next=e).prev=t,this.lastChild=e):this.lastChild=this.firstChild=e,e.parent=this,e},a.prototype.insert=function(e,t,n){var r;return e.parent&&e.remove(),r=t.parent||this,n?(t===r.firstChild?r.firstChild=e:t.prev.next=e,e.prev=t.prev,(e.next=t).prev=e):(t===r.lastChild?r.lastChild=e:t.next.prev=e,e.next=t.next,(e.prev=t).next=e),e.parent=r,e},a.prototype.getAll=function(e){var t,n=[];for(t=this.firstChild;t;t=Ry(t,this))t.name===e&&n.push(t);return n},a.prototype.empty=function(){var e,t,n;if(this.firstChild){for(e=[],n=this.firstChild;n;n=Ry(n,this))e.push(n);for(t=e.length;t--;)(n=e[t]).parent=n.firstChild=n.lastChild=n.next=n.prev=null}return this.firstChild=this.lastChild=null,this},a.prototype.isEmpty=function(e,t,n){var r,o,i=this.firstChild;if(t=t||{},i)do{if(1===i.type){if(i.attributes.map["data-mce-bogus"])continue;if(e[i.name])return!1;for(r=i.attributes.length;r--;)if("name"===(o=i.attributes[r].name)||0===o.indexOf("data-mce-bookmark"))return!1}if(8===i.type)return!1;if(3===i.type&&!Ty.test(i.value))return!1;if(3===i.type&&i.parent&&t[i.parent.name]&&Ty.test(i.value))return!1;if(n&&n(i))return!1}while(i=Ry(i,this));return!0},a.prototype.walk=function(e){return Ry(this,null,e)},a}(),By=function(e,t,n,r){(e.padd_empty_with_br||t.insert)&&n[r.name]?r.empty().append(new _y("br",1)).shortEnded=!0:r.empty().append(new _y("#text",3)).value="\xa0"},Dy=function(e){return Oy(e,"#text")&&"\xa0"===e.firstChild.value},Oy=function(e,t){return e&&e.firstChild&&e.firstChild===e.lastChild&&e.firstChild.name===t},Py=function(r,e,t,n){return n.isEmpty(e,t,function(e){return t=e,(n=r.getElementRule(t.name))&&n.paddEmpty;var t,n})},Ly=function(e,t){return e&&(t[e.name]||"br"===e.name)},Iy=function(e,g){var h=e.schema;g.remove_trailing_brs&&e.addNodeFilter("br",function(e,t,n){var r,o,i,a,u,s,c,l,f=e.length,d=It.extend({},h.getBlockElements()),m=h.getNonEmptyElements(),p=h.getNonEmptyElements();for(d.body=1,r=0;r<f;r++)if(i=(o=e[r]).parent,d[o.parent.name]&&o===i.lastChild){for(u=o.prev;u;){if("span"!==(s=u.name)||"bookmark"!==u.attr("data-mce-type")){if("br"!==s)break;if("br"===s){o=null;break}}u=u.prev}o&&(o.remove(),Py(h,m,p,i)&&(c=h.getElementRule(i.name))&&(c.removeEmpty?i.remove():c.paddEmpty&&By(g,n,d,i)))}else{for(a=o;i&&i.firstChild===a&&i.lastChild===a&&!d[(a=i).name];)i=i.parent;a===i&&!0!==g.padd_empty_with_br&&((l=new _y("#text",3)).value="\xa0",o.replace(l))}}),e.addAttributeFilter("href",function(e){var t,n,r,o=e.length;if(!g.allow_unsafe_link_target)for(;o--;)"a"===(t=e[o]).name&&"_blank"===t.attr("target")&&t.attr("rel",(n=t.attr("rel"),r=n?It.trim(n):"",/\b(noopener)\b/g.test(r)?r:r.split(" ").filter(function(e){return 0<e.length}).concat(["noopener"]).sort().join(" ")))}),g.allow_html_in_named_anchor||e.addAttributeFilter("id,name",function(e){for(var t,n,r,o,i=e.length;i--;)if("a"===(o=e[i]).name&&o.firstChild&&!o.attr("href"))for(r=o.parent,t=o.lastChild;n=t.prev,r.insert(t,o),t=n;);}),g.fix_list_elements&&e.addNodeFilter("ul,ol",function(e){for(var t,n,r=e.length;r--;)if("ul"===(n=(t=e[r]).parent).name||"ol"===n.name)if(t.prev&&"li"===t.prev.name)t.prev.append(t);else{var o=new _y("li",1);o.attr("style","list-style-type: none"),t.wrap(o)}}),g.validate&&h.getValidClasses()&&e.addAttributeFilter("class",function(e){for(var t,n,r,o,i,a,u,s=e.length,c=h.getValidClasses();s--;){for(n=(t=e[s]).attr("class").split(" "),i="",r=0;r<n.length;r++)o=n[r],u=!1,(a=c["*"])&&a[o]&&(u=!0),a=c[t.name],!u&&a&&a[o]&&(u=!0),u&&(i&&(i+=" "),i+=o);i.length||(i=null),t.attr("class",i)}})},My=It.makeMap,Fy=It.each,zy=It.explode,Uy=It.extend;function qy(k,T){void 0===T&&(T=oi());var A={},R=[],_={},B={};(k=k||{}).validate=!("validate"in k)||k.validate,k.root_name=k.root_name||"body";var D=function(e){var t,n,r;n in A&&((r=_[n])?r.push(e):_[n]=[e]),t=R.length;for(;t--;)(n=R[t].name)in e.attributes.map&&((r=B[n])?r.push(e):B[n]=[e]);return e},e={schema:T,addAttributeFilter:function(e,n){Fy(zy(e),function(e){var t;for(t=0;t<R.length;t++)if(R[t].name===e)return void R[t].callbacks.push(n);R.push({name:e,callbacks:[n]})})},getAttributeFilters:function(){return[].concat(R)},addNodeFilter:function(e,n){Fy(zy(e),function(e){var t=A[e];t||(A[e]=t=[]),t.push(n)})},getNodeFilters:function(){var e=[];for(var t in A)A.hasOwnProperty(t)&&e.push({name:t,callbacks:A[t]});return e},filterNode:D,parse:function(e,a){var t,n,r,o,i,u,s,c,l,f,d,m=[];a=a||{},_={},B={},l=Uy(My("script,style,head,html,body,title,meta,param"),T.getBlockElements());var p=T.getNonEmptyElements(),g=T.children,h=k.validate,v="forced_root_block"in a?a.forced_root_block:k.forced_root_block,y=T.getWhiteSpaceElements(),b=/^[ \t\r\n]+/,C=/[ \t\r\n]+$/,x=/[ \t\r\n]+/g,w=/^[ \t\r\n]+$/;f=y.hasOwnProperty(a.context)||y.hasOwnProperty(k.root_name);var N=function(e,t){var n,r=new _y(e,t);return e in A&&((n=_[e])?n.push(r):_[e]=[r]),r},E=function(e){var t,n,r,o,i=T.getBlockElements();for(t=e.prev;t&&3===t.type;){if(0<(r=t.value.replace(C,"")).length)return void(t.value=r);if(n=t.next){if(3===n.type&&n.value.length){t=t.prev;continue}if(!i[n.name]&&"script"!==n.name&&"style"!==n.name){t=t.prev;continue}}o=t.prev,t.remove(),t=o}};t=vh({validate:h,allow_script_urls:k.allow_script_urls,allow_conditional_comments:k.allow_conditional_comments,self_closing_elements:function(e){var t,n={};for(t in e)"li"!==t&&"p"!==t&&(n[t]=e[t]);return n}(T.getSelfClosingElements()),cdata:function(e){d.append(N("#cdata",4)).value=e},text:function(e,t){var n;f||(e=e.replace(x," "),Ly(d.lastChild,l)&&(e=e.replace(b,""))),0!==e.length&&((n=N("#text",3)).raw=!!t,d.append(n).value=e)},comment:function(e){d.append(N("#comment",8)).value=e},pi:function(e,t){d.append(N(e,7)).value=t,E(d)},doctype:function(e){d.append(N("#doctype",10)).value=e,E(d)},start:function(e,t,n){var r,o,i,a,u;if(i=h?T.getElementRule(e):{}){for((r=N(i.outputName||e,1)).attributes=t,r.shortEnded=n,d.append(r),(u=g[d.name])&&g[r.name]&&!u[r.name]&&m.push(r),o=R.length;o--;)(a=R[o].name)in t.map&&((s=B[a])?s.push(r):B[a]=[r]);l[e]&&E(r),n||(d=r),!f&&y[e]&&(f=!0)}},end:function(e){var t,n,r,o,i;if(n=h?T.getElementRule(e):{}){if(l[e]&&!f){if((t=d.firstChild)&&3===t.type)if(0<(r=t.value.replace(b,"")).length)t.value=r,t=t.next;else for(o=t.next,t.remove(),t=o;t&&3===t.type;)r=t.value,o=t.next,(0===r.length||w.test(r))&&(t.remove(),t=o),t=o;if((t=d.lastChild)&&3===t.type)if(0<(r=t.value.replace(C,"")).length)t.value=r,t=t.prev;else for(o=t.prev,t.remove(),t=o;t&&3===t.type;)r=t.value,o=t.prev,(0===r.length||w.test(r))&&(t.remove(),t=o),t=o}if(f&&y[e]&&(f=!1),n.removeEmpty&&Py(T,p,y,d)&&!d.attributes.map.name&&!d.attr("id"))return i=d.parent,l[d.name]?d.empty().remove():d.unwrap(),void(d=i);n.paddEmpty&&(Dy(d)||Py(T,p,y,d))&&By(k,a,l,d),d=d.parent}}},T);var S=d=new _y(a.context||k.root_name,11);if(t.parse(e),h&&m.length&&(a.context?a.invalid=!0:function(e){var t,n,r,o,i,a,u,s,c,l,f,d,m,p,g,h;for(d=My("tr,td,th,tbody,thead,tfoot,table"),l=T.getNonEmptyElements(),f=T.getWhiteSpaceElements(),m=T.getTextBlockElements(),p=T.getSpecialElements(),t=0;t<e.length;t++)if((n=e[t]).parent&&!n.fixed)if(m[n.name]&&"li"===n.parent.name){for(g=n.next;g&&m[g.name];)g.name="li",g.fixed=!0,n.parent.insert(g,n.parent),g=g.next;n.unwrap(n)}else{for(o=[n],r=n.parent;r&&!T.isValidChild(r.name,n.name)&&!d[r.name];r=r.parent)o.push(r);if(r&&1<o.length){for(o.reverse(),i=a=D(o[0].clone()),c=0;c<o.length-1;c++){for(T.isValidChild(a.name,o[c].name)?(u=D(o[c].clone()),a.append(u)):u=a,s=o[c].firstChild;s&&s!==o[c+1];)h=s.next,u.append(s),s=h;a=u}Py(T,l,f,i)?r.insert(n,o[0],!0):(r.insert(i,o[0],!0),r.insert(n,i)),r=o[0],(Py(T,l,f,r)||Oy(r,"br"))&&r.empty().remove()}else if(n.parent){if("li"===n.name){if((g=n.prev)&&("ul"===g.name||"ul"===g.name)){g.append(n);continue}if((g=n.next)&&("ul"===g.name||"ul"===g.name)){g.insert(n,g.firstChild,!0);continue}n.wrap(D(new _y("ul",1)));continue}T.isValidChild(n.parent.name,"div")&&T.isValidChild("div",n.name)?n.wrap(D(new _y("div",1))):p[n.name]?n.empty().remove():n.unwrap()}}}(m)),v&&("body"===S.name||a.isRootContent)&&function(){var e,t,n=S.firstChild,r=function(e){e&&((n=e.firstChild)&&3===n.type&&(n.value=n.value.replace(b,"")),(n=e.lastChild)&&3===n.type&&(n.value=n.value.replace(C,"")))};if(T.isValidChild(S.name,v.toLowerCase())){for(;n;)e=n.next,3===n.type||1===n.type&&"p"!==n.name&&!l[n.name]&&!n.attr("data-mce-type")?(t||((t=N(v,1)).attr(k.forced_root_block_attrs),S.insert(t,n)),t.append(n)):(r(t),t=null),n=e;r(t)}}(),!a.invalid){for(c in _){for(s=A[c],i=(n=_[c]).length;i--;)n[i].parent||n.splice(i,1);for(r=0,o=s.length;r<o;r++)s[r](n,c,a)}for(r=0,o=R.length;r<o;r++)if((s=R[r]).name in B){for(i=(n=B[s.name]).length;i--;)n[i].parent||n.splice(i,1);for(i=0,u=s.callbacks.length;i<u;i++)s.callbacks[i](n,s.name,a)}}return S}};return Iy(e,k),ky.register(e,k),e}var Vy=function(e,t,n){-1===It.inArray(t,n)&&(e.addAttributeFilter(n,function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),t.push(n))},Hy=function(e,t,n){var r=_i(n.getInner?t.innerHTML:e.getOuterHTML(t));return n.selection||wo(Vn.fromDom(t))?r:It.trim(r)},jy=function(e,t,n){var r=n.selection?xy.merge({forced_root_block:!1},n):n,o=e.parse(t,r);return wy.trimTrailingBr(o),o},$y=function(e,t,n,r,o){var i,a,u,s,c=(i=r,Jc(t,n).serialize(i));return a=e,s=c,!(u=o).no_events&&a?lp(a,xy.merge(u,{content:s})).content:s};function Wy(e,t){var a,u,s,c,l,n,r=(a=e,n=["data-mce-selected"],s=(u=t)&&u.dom?u.dom:vi.DOM,c=u&&u.schema?u.schema:oi(a),a.entity_encoding=a.entity_encoding||"named",a.remove_trailing_brs=!("remove_trailing_brs"in a)||a.remove_trailing_brs,l=qy(a,c),wy.register(l,a,s),{schema:c,addNodeFilter:l.addNodeFilter,addAttributeFilter:l.addAttributeFilter,serialize:function(e,t){var n=xy.merge({format:"html"},t||{}),r=Ny.process(u,e,n),o=Hy(s,r,n),i=jy(l,o,n);return"tree"===n.format?i:$y(u,a,c,i,n)},addRules:function(e){c.addValidElements(e)},setRules:function(e){c.setValidElements(e)},addTempAttr:V.curry(Vy,l,n),getTempAttrs:function(){return n}});return{schema:r.schema,addNodeFilter:r.addNodeFilter,addAttributeFilter:r.addAttributeFilter,serialize:r.serialize,addRules:r.addRules,setRules:r.setRules,addTempAttr:r.addTempAttr,getTempAttrs:r.getTempAttrs}}function Ky(e){return{getBookmark:V.curry(Lc,e),moveToBookmark:V.curry(Ic,e)}}(Ky||(Ky={})).isBookmarkNode=Mc;var Xy=Ky,Yy=Oo.isContentEditableFalse,Gy=Oo.isContentEditableTrue,Jy=function(r,a){var u,s,c,l,f,d,m,p,g,h,v,y,i,b,C,x,w,N=a.dom,E=It.each,S=a.getDoc(),k=document,T=Math.abs,A=Math.round,R=a.getBody();l={nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};var e=".mce-content-body";a.contentStyles.push(e+" div.mce-resizehandle {position: absolute;border: 1px solid black;box-sizing: content-box;background: #FFF;width: 7px;height: 7px;z-index: 10000}"+e+" .mce-resizehandle:hover {background: #000}"+e+" img[data-mce-selected],"+e+" hr[data-mce-selected] {outline: 1px solid black;resize: none}"+e+" .mce-clonedresizable {position: absolute;"+(ve.gecko?"":"outline: 1px dashed black;")+"opacity: .5;filter: alpha(opacity=50);z-index: 10000}"+e+" .mce-resize-helper {background: #555;background: rgba(0,0,0,0.75);border-radius: 3px;border: 1px;color: white;display: none;font-family: sans-serif;font-size: 12px;white-space: nowrap;line-height: 14px;margin: 5px 10px;padding: 5px;position: absolute;z-index: 10001}");var _=function(e){return e&&("IMG"===e.nodeName||a.dom.is(e,"figure.image"))},n=function(e){var t,n,r=e.target;t=e,n=a.selection.getRng(),!_(t.target)||ih(t.clientX,t.clientY,n)||e.isDefaultPrevented()||(e.preventDefault(),a.selection.select(r))},B=function(e){return a.dom.is(e,"figure.image")?e.querySelector("img"):e},D=function(e){var t=a.settings.object_resizing;return!1!==t&&!ve.iOS&&("string"!=typeof t&&(t="table,img,figure.image,div"),"false"!==e.getAttribute("data-mce-resize")&&e!==a.getBody()&&Pr.is(Vn.fromDom(e),t))},O=function(e){var t,n,r,o;t=e.screenX-d,n=e.screenY-m,b=t*f[2]+h,C=n*f[3]+v,b=b<5?5:b,C=C<5?5:C,(_(u)&&!1!==a.settings.resize_img_proportional?!sh.modifierPressed(e):sh.modifierPressed(e)||_(u)&&f[2]*f[3]!=0)&&(T(t)>T(n)?(C=A(b*y),b=A(C/y)):(b=A(C/y),C=A(b*y))),N.setStyles(B(s),{width:b,height:C}),r=0<(r=f.startPos.x+t)?r:0,o=0<(o=f.startPos.y+n)?o:0,N.setStyles(c,{left:r,top:o,display:"block"}),c.innerHTML=b+" × "+C,f[2]<0&&s.clientWidth<=b&&N.setStyle(s,"left",p+(h-b)),f[3]<0&&s.clientHeight<=C&&N.setStyle(s,"top",g+(v-C)),(t=R.scrollWidth-x)+(n=R.scrollHeight-w)!=0&&N.setStyles(c,{left:r-t,top:o-n}),i||(mp(a,u,h,v),i=!0)},P=function(){i=!1;var e=function(e,t){t&&(u.style[e]||!a.schema.isValid(u.nodeName.toLowerCase(),e)?N.setStyle(B(u),e,t):N.setAttrib(B(u),e,t))};e("width",b),e("height",C),N.unbind(S,"mousemove",O),N.unbind(S,"mouseup",P),k!==S&&(N.unbind(k,"mousemove",O),N.unbind(k,"mouseup",P)),N.remove(s),N.remove(c),o(u),pp(a,u,b,C),N.setAttrib(u,"style",N.getAttrib(u,"style")),a.nodeChanged()},o=function(e){var t,r,o,n,i;L(),F(),t=N.getPos(e,R),p=t.x,g=t.y,i=e.getBoundingClientRect(),r=i.width||i.right-i.left,o=i.height||i.bottom-i.top,u!==e&&(u=e,b=C=0),n=a.fire("ObjectSelected",{target:e}),D(e)&&!n.isDefaultPrevented()?E(l,function(n,e){var t;(t=N.get("mceResizeHandle"+e))&&N.remove(t),t=N.add(R,"div",{id:"mceResizeHandle"+e,"data-mce-bogus":"all","class":"mce-resizehandle",unselectable:!0,style:"cursor:"+e+"-resize; margin:0; padding:0"}),11===ve.ie&&(t.contentEditable=!1),N.bind(t,"mousedown",function(e){var t;e.stopImmediatePropagation(),e.preventDefault(),d=(t=e).screenX,m=t.screenY,h=B(u).clientWidth,v=B(u).clientHeight,y=v/h,(f=n).startPos={x:r*n[0]+p,y:o*n[1]+g},x=R.scrollWidth,w=R.scrollHeight,s=u.cloneNode(!0),N.addClass(s,"mce-clonedresizable"),N.setAttrib(s,"data-mce-bogus","all"),s.contentEditable=!1,s.unSelectabe=!0,N.setStyles(s,{left:p,top:g,margin:0}),s.removeAttribute("data-mce-selected"),R.appendChild(s),N.bind(S,"mousemove",O),N.bind(S,"mouseup",P),k!==S&&(N.bind(k,"mousemove",O),N.bind(k,"mouseup",P)),c=N.add(R,"div",{"class":"mce-resize-helper","data-mce-bogus":"all"},h+" × "+v)}),n.elm=t,N.setStyles(t,{left:r*n[0]+p-t.offsetWidth/2,top:o*n[1]+g-t.offsetHeight/2})}):L(),u.setAttribute("data-mce-selected","1")},L=function(){var e,t;for(e in F(),u&&u.removeAttribute("data-mce-selected"),l)(t=N.get("mceResizeHandle"+e))&&(N.unbind(t),N.remove(t))},I=function(e){var t,n=function(e,t){if(e)do{if(e===t)return!0}while(e=e.parentNode)};i||a.removed||(E(N.select("img[data-mce-selected],hr[data-mce-selected]"),function(e){e.removeAttribute("data-mce-selected")}),t="mousedown"===e.type?e.target:r.getNode(),n(t=N.$(t).closest("table,img,figure.image,hr")[0],R)&&(z(),n(r.getStart(!0),t)&&n(r.getEnd(!0),t))?o(t):L())},M=function(e){return Yy(function(e,t){for(;t&&t!==e;){if(Gy(t)||Yy(t))return t;t=t.parentNode}return null}(a.getBody(),e))},F=function(){for(var e in l){var t=l[e];t.elm&&(N.unbind(t.elm),delete t.elm)}},z=function(){try{a.getDoc().execCommand("enableObjectResizing",!1,!1)}catch(e){}};return a.on("init",function(){z(),ve.ie&&11<=ve.ie&&(a.on("mousedown click",function(e){var t=e.target,n=t.nodeName;i||!/^(TABLE|IMG|HR)$/.test(n)||M(t)||(2!==e.button&&a.selection.select(t,"TABLE"===n),"mousedown"===e.type&&a.nodeChanged())}),a.dom.bind(R,"mscontrolselect",function(e){var t=function(e){we.setEditorTimeout(a,function(){a.selection.select(e)})};if(M(e.target))return e.preventDefault(),void t(e.target);/^(TABLE|IMG|HR)$/.test(e.target.nodeName)&&(e.preventDefault(),"IMG"===e.target.tagName&&t(e.target))}));var t=we.throttle(function(e){a.composing||I(e)});a.on("nodechange ResizeEditor ResizeWindow drop FullscreenStateChanged",t),a.on("keyup compositionend",function(e){u&&"TABLE"===u.nodeName&&t(e)}),a.on("hide blur",L),a.on("contextmenu",n)}),a.on("remove",F),{isResizable:D,showResizeRect:o,hideResizeRect:L,updateResizeRect:I,destroy:function(){u=s=null}}},Qy=function(e){return Oo.isContentEditableTrue(e)||Oo.isContentEditableFalse(e)},Zy=function(e,t,n){var r,o,i,a,u,s=n;if(s.caretPositionFromPoint)(o=s.caretPositionFromPoint(e,t))&&((r=n.createRange()).setStart(o.offsetNode,o.offset),r.collapse(!0));else if(n.caretRangeFromPoint)r=n.caretRangeFromPoint(e,t);else if(s.body.createTextRange){r=s.body.createTextRange();try{r.moveToPoint(e,t),r.collapse(!0)}catch(c){r=function(e,n,t){var r,o,i;if(r=t.elementFromPoint(e,n),o=t.body.createTextRange(),r&&"HTML"!==r.tagName||(r=t.body),o.moveToElementText(r),0<(i=(i=It.toArray(o.getClientRects())).sort(function(e,t){return(e=Math.abs(Math.max(e.top-n,e.bottom-n)))-(t=Math.abs(Math.max(t.top-n,t.bottom-n)))})).length){n=(i[0].bottom+i[0].top)/2;try{return o.moveToPoint(e,n),o.collapse(!0),o}catch(a){}}return null}(e,t,n)}return i=r,a=n.body,u=i&&i.parentElement?i.parentElement():null,Oo.isContentEditableFalse(function(e,t,n){for(;e&&e!==t;){if(n(e))return e;e=e.parentNode}return null}(u,a,Qy))?null:i}return r},eb=function(n,e){return H.map(e,function(e){var t=n.fire("GetSelectionRange",{range:e});return t.range!==e?t.range:e})},tb=function(e,t){return Vn.fromDom(e.dom().cloneNode(t))},nb=function(e){return tb(e,!0)},rb=function(e){return tb(e,!1)},ob=nb,ib=function(e,t){var n=(t||document).createDocumentFragment();return H.each(e,function(e){n.appendChild(e.dom())}),Vn.fromDom(n)},ab=kr.immutable("element","width","rows"),ub=kr.immutable("element","cells"),sb=kr.immutable("x","y"),cb=function(e,t){var n=parseInt(lr.get(e,t),10);return isNaN(n)?1:n},lb=function(e){return H.foldl(e,function(e,t){return t.cells().length>e?t.cells().length:e},0)},fb=function(e,t){for(var n=e.rows(),r=0;r<n.length;r++)for(var o=n[r].cells(),i=0;i<o.length;i++)if(Mr.eq(o[i],t))return A.some(sb(i,r));return A.none()},db=function(e,t,n,r,o){for(var i=[],a=e.rows(),u=n;u<=o;u++){var s=a[u].cells(),c=t<r?s.slice(t,r+1):s.slice(r,t+1);i.push(ub(a[u].element(),c))}return i},mb=function(e){var o=ab(rb(e),0,[]);return H.each(hu(e,"tr"),function(n,r){H.each(hu(n,"td,th"),function(e,t){!function(e,t,n,r,o){for(var i=cb(o,"rowspan"),a=cb(o,"colspan"),u=e.rows(),s=n;s<n+i;s++){u[s]||(u[s]=ub(ob(r),[]));for(var c=t;c<t+a;c++)u[s].cells()[c]=s===n&&c===t?o:rb(o)}}(o,function(e,t,n){for(;r=t,o=n,i=void 0,((i=e.rows())[o]?i[o].cells():[])[r];)t++;var r,o,i;return t}(o,t,r),r,n,e)})}),ab(o.element(),lb(o.rows()),o.rows())},pb=function(e){return i=t=e,n=H.map(i.rows(),function(e){var t=H.map(e.cells(),function(e){var t=ob(e);return lr.remove(t,"colspan"),lr.remove(t,"rowspan"),t}),n=rb(e.element());return qc(n,t),n}),r=rb(t.element()),o=Vn.fromTag("tbody"),qc(o,n),Hu.append(r,o),r;var t,n,r,o,i},gb=function(l,e,t){return fb(l,e).bind(function(c){return fb(l,t).map(function(e){return t=l,r=e,o=(n=c).x(),i=n.y(),a=r.x(),u=r.y(),s=i<u?db(t,o,i,a,u):db(t,o,u,a,i),ab(t.element(),lb(s),s);var t,n,r,o,i,a,u,s})})},hb=function(n,t){return H.find(n,function(e){return"li"===Zn.name(e)&&Rg(e,t)}).fold(V.constant([]),function(e){return(t=n,H.find(t,function(e){return"ul"===Zn.name(e)||"ol"===Zn.name(e)})).map(function(e){return[Vn.fromTag("li"),Vn.fromTag(Zn.name(e))]}).getOr([]);var t})},vb=function(e,t){var n,r=Vn.fromDom(t.commonAncestorContainer),o=jl(r,e),i=H.filter(o,function(e){return po(e)||fo(e)}),a=hb(o,t),u=i.concat(a.length?a:yo(n=r)?$r.parent(n).filter(vo).fold(V.constant([]),function(e){return[n,e]}):vo(n)?[n]:[]);return H.map(u,rb)},yb=function(){return ib([])},bb=function(e,t){return n=Vn.fromDom(t.cloneContents()),r=vb(e,t),o=H.foldl(r,function(e,t){return Hu.append(t,e),t},n),0<r.length?ib([o]):o;var n,r,o},Cb=function(e,o){return(t=e,n=o[0],kl(n,"table",V.curry(Mr.eq,t))).bind(function(e){var t=o[0],n=o[o.length-1],r=mb(e);return gb(r,t,n).map(function(e){return ib([pb(e)])})}).getOrThunk(yb);var t,n},xb=function(e,t){var n,r,o=Pd(t,e);return 0<o.length?Cb(e,o):(n=e,0<(r=t).length&&r[0].collapsed?yb():bb(n,r[0]))},wb=function(e,t){var n,r=e.selection.getRng(),o=e.dom.create("body"),i=e.selection.getSel(),a=eb(e,Ad(i));if((t=t||{}).get=!0,t.format=t.format||"html",t.selection=!0,(t=e.fire("BeforeGetContent",t)).isDefaultPrevented())return e.fire("GetContent",t),t.content;if("text"===t.format)return e.selection.isCollapsed()?"":_i(r.text||(i.toString?i.toString():""));r.cloneContents?(n=t.contextual?xb(Vn.fromDom(e.getBody()),a).dom():r.cloneContents())&&o.appendChild(n):r.item!==undefined||r.htmlText!==undefined?(o.innerHTML="<br>"+(r.item?r.item(0).outerHTML:r.htmlText),o.removeChild(o.firstChild)):o.innerHTML=r.toString(),t.getInner=!0;var u=e.selection.serializer.serialize(o,t);return"tree"===t.format?u:(t.content=e.selection.isCollapsed()?"":u,e.fire("GetContent",t),t.content)},Nb=function(e,t,n){var r,o,i,a=e.selection.getRng(),u=e.getDoc();if((n=n||{format:"html"}).set=!0,n.selection=!0,n.content=t,n.no_events||!(n=e.fire("BeforeSetContent",n)).isDefaultPrevented()){if(t=n.content,a.insertNode){t+='<span id="__caret">_</span>',a.startContainer===u&&a.endContainer===u?u.body.innerHTML=t:(a.deleteContents(),0===u.body.childNodes.length?u.body.innerHTML=t:a.createContextualFragment?a.insertNode(a.createContextualFragment(t)):(o=u.createDocumentFragment(),i=u.createElement("div"),o.appendChild(i),i.outerHTML=t,a.insertNode(o))),r=e.dom.get("__caret"),(a=u.createRange()).setStartBefore(r),a.setEndBefore(r),e.selection.setRng(a),e.dom.remove("__caret");try{e.selection.setRng(a)}catch(s){}}else a.item&&(u.execCommand("Delete",!1,null),a=e.getRng()),/^\s+/.test(t)?(a.pasteHTML('<span id="__mce_tmp">_</span>'+t),e.dom.remove("__mce_tmp")):a.pasteHTML(t);n.no_events||e.fire("SetContent",n)}else e.fire("SetContent",n)},Eb=function(e,t,n,r,o){var i=n?t.startContainer:t.endContainer,a=n?t.startOffset:t.endOffset;return A.from(i).map(Vn.fromDom).map(function(e){return r&&t.collapsed?e:$r.child(e,o(e,a)).getOr(e)}).bind(function(e){return Zn.isElement(e)?A.some(e):$r.parent(e)}).map(function(e){return e.dom()}).getOr(e)},Sb=function(e,t,n){return Eb(e,t,!0,n,function(e,t){return Math.min($r.childNodesCount(e),t)})},kb=function(e,t,n){return Eb(e,t,!1,n,function(e,t){return 0<t?t-1:t})},Tb=function(e,t){for(var n=e;e&&Oo.isText(e)&&0===e.length;)e=t?e.nextSibling:e.previousSibling;return e||n},Ab=It.each,Rb=function(e){return!!e.select},_b=function(e){return!(!e||!e.ownerDocument)&&Mr.contains(Vn.fromDom(e.ownerDocument),Vn.fromDom(e))},Bb=function(u,s,e,c){var n,t,l,f,a,r=function(e,t){return Nb(c,e,t)},o=function(e){var t=m();t.collapse(!!e),i(t)},d=function(){return s.getSelection?s.getSelection():s.document.selection},m=function(){var e,t,n,r,o=function(e,t,n){try{return t.compareBoundaryPoints(e,n)}catch(r){return-1}};if(!s)return null;if(null==(r=s.document))return null;if(c.bookmark!==undefined&&!1===zp(c)){var i=Mm(c);if(i.isSome())return i.map(function(e){return eb(c,[e])[0]}).getOr(r.createRange())}try{(e=d())&&(t=0<e.rangeCount?e.getRangeAt(0):e.createRange?e.createRange():r.createRange())}catch(a){}return(t=eb(c,[t])[0])||(t=r.createRange?r.createRange():r.body.createTextRange()),t.setStart&&9===t.startContainer.nodeType&&t.collapsed&&(n=u.getRoot(),t.setStart(n,0),t.setEnd(n,0)),l&&f&&(0===o(t.START_TO_START,t,l)&&0===o(t.END_TO_END,t,l)?t=f:f=l=null),t},i=function(e,t){var n,r;if((o=e)&&(Rb(o)||_b(o.startContainer)&&_b(o.endContainer))){var o,i=Rb(e)?e:null;if(i){f=null;try{i.select()}catch(a){}}else{if(n=d(),e=c.fire("SetSelectionRange",{range:e,forward:t}).range,n){f=e;try{n.removeAllRanges(),n.addRange(e)}catch(a){}!1===t&&n.extend&&(n.collapse(e.endContainer,e.endOffset),n.extend(e.startContainer,e.startOffset)),l=0<n.rangeCount?n.getRangeAt(0):null}e.collapsed||e.startContainer!==e.endContainer||!n.setBaseAndExtent||ve.ie||e.endOffset-e.startOffset<2&&e.startContainer.hasChildNodes()&&(r=e.startContainer.childNodes[e.startOffset])&&"IMG"===r.tagName&&(n.setBaseAndExtent(e.startContainer,e.startOffset,e.endContainer,e.endOffset),n.anchorNode===e.startContainer&&n.focusNode===e.endContainer||n.setBaseAndExtent(r,0,r,1)),c.fire("AfterSetSelectionRange",{range:e,forward:t})}}},p=function(){var e,t,n=d();return!(n&&n.anchorNode&&n.focusNode)||((e=u.createRng()).setStart(n.anchorNode,n.anchorOffset),e.collapse(!0),(t=u.createRng()).setStart(n.focusNode,n.focusOffset),t.collapse(!0),e.compareBoundaryPoints(e.START_TO_START,t)<=0)},g={bookmarkManager:null,controlSelection:null,dom:u,win:s,serializer:e,editor:c,collapse:o,setCursorLocation:function(e,t){var n=u.createRng();e?(n.setStart(e,t),n.setEnd(e,t),i(n),o(!1)):(_g(u,n,c.getBody(),!0),i(n))},getContent:function(e){return wb(c,e)},setContent:r,getBookmark:function(e,t){return n.getBookmark(e,t)},moveToBookmark:function(e){return n.moveToBookmark(e)},select:function(e,t){var r,n,o;return(r=u,n=e,o=t,A.from(n).map(function(e){var t=r.nodeIndex(e),n=r.createRng();return n.setStart(e.parentNode,t),n.setEnd(e.parentNode,t+1),o&&(_g(r,n,e,!0),_g(r,n,e,!1)),n})).each(i),e},isCollapsed:function(){var e=m(),t=d();return!(!e||e.item)&&(e.compareEndPoints?0===e.compareEndPoints("StartToEnd",e):!t||e.collapsed)},isForward:p,setNode:function(e){return r(u.getOuterHTML(e)),e},getNode:function(){return e=c.getBody(),(t=m())?(r=t.startContainer,o=t.endContainer,i=t.startOffset,a=t.endOffset,n=t.commonAncestorContainer,!t.collapsed&&(r===o&&a-i<2&&r.hasChildNodes()&&(n=r.childNodes[i]),3===r.nodeType&&3===o.nodeType&&(r=r.length===i?Tb(r.nextSibling,!0):r.parentNode,o=0===a?Tb(o.previousSibling,!1):o.parentNode,r&&r===o))?r:n&&3===n.nodeType?n.parentNode:n):e;var e,t,n,r,o,i,a},getSel:d,setRng:i,getRng:m,getStart:function(e){return Sb(c.getBody(),m(),e)},getEnd:function(e){return kb(c.getBody(),m(),e)},getSelectedBlocks:function(e,t){return function(e,t,n,r){var o,i,a=[];if(i=e.getRoot(),n=e.getParent(n||Sb(i,t,!1),e.isBlock),r=e.getParent(r||kb(i,t,!1),e.isBlock),n&&n!==i&&a.push(n),n&&r&&n!==r)for(var u=new ao(o=n,i);(o=u.next())&&o!==r;)e.isBlock(o)&&a.push(o);return r&&n!==r&&r!==i&&a.push(r),a}(u,m(),e,t)},normalize:function(){var e=m(),t=d();if(!_d(t)&&Bg(c)){var n=um(u,e);return n.each(function(e){i(e,p())}),n.getOr(e)}return e},selectorChanged:function(e,t){var i;return a||(a={},i={},c.on("NodeChange",function(e){var n=e.element,r=u.getParents(n,null,u.getRoot()),o={};Ab(a,function(e,n){Ab(r,function(t){if(u.is(t,n))return i[n]||(Ab(e,function(e){e(!0,{node:t,selector:n,parents:r})}),i[n]=e),o[n]=e,!1})}),Ab(i,function(e,t){o[t]||(delete i[t],Ab(e,function(e){e(!1,{node:n,selector:t,parents:r})}))})})),a[e]||(a[e]=[]),a[e].push(t),g},getScrollContainer:function(){for(var e,t=u.getRoot();t&&"BODY"!==t.nodeName;){if(t.scrollHeight>t.clientHeight){e=t;break}t=t.parentNode}return e},scrollIntoView:function(e,t){return Nu(c,e,t)},placeCaretAt:function(e,t){return i(Zy(e,t,c.getDoc()))},getBoundingClientRect:function(){var e=m();return e.collapsed?La.fromRangeStart(e).getClientRects()[0]:e.getBoundingClientRect()},destroy:function(){s=l=f=null,t.destroy()}};return n=Xy(g),t=Jy(g,c),g.bookmarkManager=n,g.controlSelection=t,g},Db=Oo.isContentEditableFalse,Ob=aa,Pb=Bs,Lb=_s,Ib=function(e,t){for(;t=e(t);)if(t.isVisible())return t;return t},Mb=function(e,t,n,r){var o,i,a,u,s,c,l=e===iu.Forwards,f=l?Lb:Pb;return!r.collapsed&&(o=Ob(r),Db(o))?tu(e,t,o,e===iu.Backwards,!0):(u=Oi(r.startContainer),f(i=Rs(e,t.getBody(),r))?nu(t,i.getNode(!l)):(i=n(i))?f(i)?tu(e,t,i.getNode(!l),l,!0):f(a=n(i))&&(!(c=bs(s=i,a))&&Oo.isBr(s.getNode())||c)?tu(e,t,a.getNode(!l),l,!0):u?ou(t,i.toRange(),!0):null:u?r:null)},Fb=function(e,t,n,r){var o,i,a,u,s,c,l,f,d;if(d=Ob(r),o=Rs(e,t.getBody(),r),i=n(t.getBody(),Yg(1),o),a=Bt.filter(i,Gg(1)),s=Bt.last(o.getClientRects()),(Lb(o)||Ds(o))&&(d=o.getNode()),(Pb(o)||Os(o))&&(d=o.getNode(!0)),!s)return null;if(c=s.left,(u=nh(a,c))&&Db(u.node))return l=Math.abs(c-u.left),f=Math.abs(c-u.right),tu(e,t,u.node,l<f,!0);if(d){var m=function(e,t,n,r){var o,i,a,u,s,c,l=Ys(t),f=[],d=0,m=function(e){return Bt.last(e.getClientRects())};1===e?(o=l.next,i=ia,a=oa,u=La.after(r)):(o=l.prev,i=oa,a=ia,u=La.before(r)),c=m(u);do{if(u.isVisible()&&!a(s=m(u),c)){if(0<f.length&&i(s,Bt.last(f))&&d++,(s=ta(s)).position=u,s.line=d,n(s))return f;f.push(s)}}while(u=o(u));return f}(e,t.getBody(),Yg(1),d);if(u=nh(Bt.filter(m,Gg(1)),c))return ou(t,u.position.toRange(),!0);if(u=Bt.last(Bt.filter(m,Gg(0))))return ou(t,u.position.toRange(),!0)}},zb=function(e,t,n){var r,o,i,a,u=Ys(e.getBody()),s=da.curry(Ib,u.next),c=da.curry(Ib,u.prev);if(n.collapsed&&e.settings.forced_root_block){if(!(r=e.dom.getParent(n.startContainer,"PRE")))return;(1===t?s(La.fromRangeStart(n)):c(La.fromRangeStart(n)))||(a=(i=e).dom.create(i.settings.forced_root_block),(!ve.ie||11<=ve.ie)&&(a.innerHTML='<br data-mce-bogus="1">'),o=a,1===t?e.$(r).after(o):e.$(r).before(o),e.selection.select(o,!0),e.selection.collapse())}},Ub=function(l,f){return function(){var e,t,n,r,o,i,a,u,s,c=(t=f,r=Ys((e=l).getBody()),o=da.curry(Ib,r.next),i=da.curry(Ib,r.prev),a=t?iu.Forwards:iu.Backwards,u=t?o:i,s=e.selection.getRng(),(n=Mb(a,e,u,s))?n:(n=zb(e,a,s))||null);return!!c&&(l.selection.setRng(c),!0)}},qb=function(u,s){return function(){var e,t,n,r,o,i,a=(r=(t=s)?1:-1,o=t?Xg:Kg,i=(e=u).selection.getRng(),(n=Fb(r,e,o,i))?n:(n=zb(e,r,i))||null);return!!a&&(u.selection.setRng(a),!0)}},Vb=function(e,r){return H.bind((t=e,H.map(t,function(e){return xy.merge({shiftKey:!1,altKey:!1,ctrlKey:!1,metaKey:!1,keyCode:0,action:V.noop},e)})),function(e){return t=e,(n=r).keyCode===t.keyCode&&n.shiftKey===t.shiftKey&&n.altKey===t.altKey&&n.ctrlKey===t.ctrlKey&&n.metaKey===t.metaKey?[e]:[];var t,n});var t},Hb=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,r)}},jb=function(e,t){return H.find(Vb(e,t),function(e){return e.action()})},$b=function(i,a){i.on("keydown",function(e){var t,n,r,o;!1===e.isDefaultPrevented()&&(t=i,n=a,r=e,o=Un.detect().os,jb([{keyCode:sh.RIGHT,action:Ub(t,!0)},{keyCode:sh.LEFT,action:Ub(t,!1)},{keyCode:sh.UP,action:qb(t,!1)},{keyCode:sh.DOWN,action:qb(t,!0)},{keyCode:sh.RIGHT,action:es(t,!0)},{keyCode:sh.LEFT,action:es(t,!1)},{keyCode:sh.UP,action:ts(t,!1)},{keyCode:sh.DOWN,action:ts(t,!0)},{keyCode:sh.RIGHT,action:sd.move(t,n,!0)},{keyCode:sh.LEFT,action:sd.move(t,n,!1)},{keyCode:sh.RIGHT,ctrlKey:!o.isOSX(),altKey:o.isOSX(),action:sd.moveNextWord(t,n)},{keyCode:sh.LEFT,ctrlKey:!o.isOSX(),altKey:o.isOSX(),action:sd.movePrevWord(t,n)}],r).each(function(e){r.preventDefault()}))})},Wb=function(e){return 1===$r.children(e).length},Kb=function(e,t,n,r){var o,i,a,u,s=V.curry(Sv,t),c=H.map(H.filter(r,s),function(e){return e.dom()});if(0===c.length)vf(t,e,n);else{var l=(o=n.dom(),i=c,a=yv(!1),u=Nv(i,a.dom()),Hu.before(Vn.fromDom(o),a),Hc.remove(Vn.fromDom(o)),La(u,0));t.selection.setRng(l.toRange())}},Xb=function(n,r){var t,e=Vn.fromDom(n.getBody()),o=Vn.fromDom(n.selection.getStart()),i=H.filter((t=jl(o,e),H.findIndex(t,mo).fold(V.constant(t),function(e){return t.slice(0,e)})),Wb);return H.last(i).map(function(e){var t=La.fromRangeStart(n.selection.getRng());return!!El(r,t,e.dom())&&(Kb(r,n,e,i),!0)}).getOr(!1)},Yb=function(e,t){return!!e.selection.isCollapsed()&&Xb(e,t)},Gb=function(o,i){o.on("keydown",function(e){var t,n,r;!1===e.isDefaultPrevented()&&(t=o,n=i,r=e,jb([{keyCode:sh.BACKSPACE,action:Hb(Cf,t,!1)},{keyCode:sh.DELETE,action:Hb(Cf,t,!0)},{keyCode:sh.BACKSPACE,action:Hb(dd,t,n,!1)},{keyCode:sh.DELETE,action:Hb(dd,t,n,!0)},{keyCode:sh.BACKSPACE,action:Hb(tf,t,!1)},{keyCode:sh.DELETE,action:Hb(tf,t,!0)},{keyCode:sh.BACKSPACE,action:Hb(Jl,t,!1)},{keyCode:sh.DELETE,action:Hb(Jl,t,!0)},{keyCode:sh.BACKSPACE,action:Hb($d,t,!1)},{keyCode:sh.DELETE,action:Hb($d,t,!0)},{keyCode:sh.BACKSPACE,action:Hb(Yb,t,!1)},{keyCode:sh.DELETE,action:Hb(Yb,t,!0)}],r).each(function(e){r.preventDefault()}))}),o.on("keyup",function(e){var t,n;!1===e.isDefaultPrevented()&&(t=o,n=e,jb([{keyCode:sh.BACKSPACE,action:Hb(xf,t)},{keyCode:sh.DELETE,action:Hb(xf,t)}],n))})},Jb=function(e){return A.from(e.dom.getParent(e.selection.getStart(!0),e.dom.isBlock))},Qb=function(e,t){var n,r,o,i=t,a=e.dom,u=e.schema.getMoveCaretBeforeOnEnterElements();if(t){if(/^(LI|DT|DD)$/.test(t.nodeName)){var s=function(e){for(;e;){if(1===e.nodeType||3===e.nodeType&&e.data&&/[\r\n\s]/.test(e.data))return e;e=e.nextSibling}}(t.firstChild);s&&/^(UL|OL|DL)$/.test(s.nodeName)&&t.insertBefore(a.doc.createTextNode("\xa0"),t.firstChild)}if(o=a.createRng(),t.normalize(),t.hasChildNodes()){for(n=new ao(t,t);r=n.current();){if(Oo.isText(r)){o.setStart(r,0),o.setEnd(r,0);break}if(u[r.nodeName.toLowerCase()]){o.setStartBefore(r),o.setEndBefore(r);break}i=r,r=n.next()}r||(o.setStart(i,0),o.setEnd(i,0))}else Oo.isBr(t)?t.nextSibling&&a.isBlock(t.nextSibling)?(o.setStartBefore(t),o.setEndBefore(t)):(o.setStartAfter(t),o.setEndAfter(t)):(o.setStart(t,0),o.setEnd(t,0));e.selection.setRng(o),a.remove(void 0),e.selection.scrollIntoView(t)}},Zb=function(e,t){var n,r,o=e.getRoot();for(n=t;n!==o&&"false"!==e.getContentEditable(n);)"true"===e.getContentEditable(n)&&(r=n),n=n.parentNode;return n!==o?r:o},eC=Jb,tC=function(e){return Jb(e).fold(V.constant(""),function(e){return e.nodeName.toUpperCase()})},nC=function(e){return Jb(e).filter(function(e){return yo(Vn.fromDom(e))}).isSome()},rC=function(e,t){return e&&e.parentNode&&e.parentNode.nodeName===t},oC=function(e){return e&&/^(OL|UL|LI)$/.test(e.nodeName)},iC=function(e){var t=e.parentNode;return/^(LI|DT|DD)$/.test(t.nodeName)?t:e},aC=function(e,t,n){for(var r=e[n?"firstChild":"lastChild"];r&&!Oo.isElement(r);)r=r[n?"nextSibling":"previousSibling"];return r===t},uC=function(e,t,n,r,o){var i=e.dom,a=e.selection.getRng();if(n!==e.getBody()){var u;oC(u=n)&&oC(u.parentNode)&&(o="LI");var s,c,l=o?t(o):i.create("BR");if(aC(n,r,!0)&&aC(n,r,!1))rC(n,"LI")?i.insertAfter(l,iC(n)):i.replace(l,n);else if(aC(n,r,!0))rC(n,"LI")?(i.insertAfter(l,iC(n)),l.appendChild(i.doc.createTextNode(" ")),l.appendChild(n)):n.parentNode.insertBefore(l,n);else if(aC(n,r,!1))i.insertAfter(l,iC(n));else{n=iC(n);var f=a.cloneRange();f.setStartAfter(r),f.setEndAfter(n);var d=f.extractContents();"LI"===o&&(c="LI",(s=d).firstChild&&s.firstChild.nodeName===c)?(l=d.firstChild,i.insertAfter(d,n)):(i.insertAfter(d,n),i.insertAfter(l,n))}i.remove(r),Qb(e,l)}},sC=function(e){e.innerHTML='<br data-mce-bogus="1">'},cC=function(e,t){return e.nodeName===t||e.previousSibling&&e.previousSibling.nodeName===t},lC=function(e,t){return t&&e.isBlock(t)&&!/^(TD|TH|CAPTION|FORM)$/.test(t.nodeName)&&!/^(fixed|absolute)/i.test(t.style.position)&&"true"!==e.getContentEditable(t)},fC=function(e,t,n){return!1===Oo.isText(t)?n:e?1===n&&t.data.charAt(n-1)===Ri?0:n:n===t.data.length-1&&t.data.charAt(n)===Ri?t.data.length:n},dC=function(e,t){var n,r,o=e.getRoot();for(n=t;n!==o&&"false"!==e.getContentEditable(n);)"true"===e.getContentEditable(n)&&(r=n),n=n.parentNode;return n!==o?r:o},mC=function(e,t){var n=Ou(e);n&&n.toLowerCase()===t.tagName.toLowerCase()&&e.dom.setAttribs(t,Pu(e))},pC=function(a,e){var t,u,s,i,c,n,r,o,l,f,d,m,p,g,h,v,y,b,C=a.dom,x=a.schema,w=x.getNonEmptyElements(),N=a.selection.getRng(),E=function(e){var t,n,r,o=s,i=x.getTextInlineElements();if(e||"TABLE"===f||"HR"===f?(t=C.create(e||m),mC(a,t)):t=c.cloneNode(!1),r=t,!1===Mu(a))C.setAttrib(t,"style",null),C.setAttrib(t,"class",null);else do{if(i[o.nodeName]){if(kc(o))continue;n=o.cloneNode(!1),C.setAttrib(n,"id",""),t.hasChildNodes()?n.appendChild(t.firstChild):r=n,t.appendChild(n)}}while((o=o.parentNode)&&o!==u);return sC(r),t},S=function(e){var t,n,r,o;if(o=fC(e,s,i),Oo.isText(s)&&(e?0<o:o<s.nodeValue.length))return!1;if(s.parentNode===c&&p&&!e)return!0;if(e&&Oo.isElement(s)&&s===c.firstChild)return!0;if(cC(s,"TABLE")||cC(s,"HR"))return p&&!e||!p&&e;for(t=new ao(s,c),Oo.isText(s)&&(e&&0===o?t.prev():e||o!==s.nodeValue.length||t.next());n=t.current();){if(Oo.isElement(n)){if(!n.getAttribute("data-mce-bogus")&&(r=n.nodeName.toLowerCase(),w[r]&&"br"!==r))return!1}else if(Oo.isText(n)&&!/^[ \t\r\n]*$/.test(n.nodeValue))return!1;e?t.prev():t.next()}return!0},k=function(){r=/^(H[1-6]|PRE|FIGURE)$/.test(f)&&"HGROUP"!==d?E(m):E(),Fu(a)&&lC(C,l)&&C.isEmpty(c)?r=C.split(l,c):C.insertAfter(r,c),Qb(a,r)};um(C,N).each(function(e){N.setStart(e.startContainer,e.startOffset),N.setEnd(e.endContainer,e.endOffset)}),s=N.startContainer,i=N.startOffset,m=Ou(a),n=e.shiftKey,Oo.isElement(s)&&s.hasChildNodes()&&(p=i>s.childNodes.length-1,s=s.childNodes[Math.min(i,s.childNodes.length-1)]||s,i=p&&Oo.isText(s)?s.nodeValue.length:0),(u=dC(C,s))&&((m&&!n||!m&&n)&&(s=function(e,t,n,r,o){var i,a,u,s,c,l,f,d=t||"P",m=e.dom,p=dC(m,r);if(!(a=m.getParent(r,m.isBlock))||!lC(m,a)){if(l=(a=a||p)===e.getBody()||(f=a)&&/^(TD|TH|CAPTION)$/.test(f.nodeName)?a.nodeName.toLowerCase():a.parentNode.nodeName.toLowerCase(),!a.hasChildNodes())return i=m.create(d),mC(e,i),a.appendChild(i),n.setStart(i,0),n.setEnd(i,0),i;for(s=r;s.parentNode!==a;)s=s.parentNode;for(;s&&!m.isBlock(s);)s=(u=s).previousSibling;if(u&&e.schema.isValidChild(l,d.toLowerCase())){for(i=m.create(d),mC(e,i),u.parentNode.insertBefore(i,u),s=u;s&&!m.isBlock(s);)c=s.nextSibling,i.appendChild(s),s=c;n.setStart(r,o),n.setEnd(r,o)}}return r}(a,m,N,s,i)),c=C.getParent(s,C.isBlock),l=c?C.getParent(c.parentNode,C.isBlock):null,f=c?c.nodeName.toUpperCase():"","LI"!==(d=l?l.nodeName.toUpperCase():"")||e.ctrlKey||(l=(c=l).parentNode,f=d),/^(LI|DT|DD)$/.test(f)&&C.isEmpty(c)?uC(a,E,l,c,m):m&&c===a.getBody()||(m=m||"P",Oi(c)?(r=Vi(c),C.isEmpty(c)&&sC(c),Qb(a,r)):S()?k():S(!0)?(r=c.parentNode.insertBefore(E(),c),Qb(a,cC(c,"HR")?r:c)):((t=(y=N,b=y.cloneRange(),b.setStart(y.startContainer,fC(!0,y.startContainer,y.startOffset)),b.setEnd(y.endContainer,fC(!1,y.endContainer,y.endOffset)),b).cloneRange()).setEndAfter(c),function(e){for(;Oo.isText(e)&&(e.nodeValue=e.nodeValue.replace(/^[\r\n]+/,"")),e=e.firstChild;);}(o=t.extractContents()),r=o.firstChild,C.insertAfter(o,c),function(e,t,n){var r,o=n,i=[];if(o){for(;o=o.firstChild;){if(e.isBlock(o))return;Oo.isElement(o)&&!t[o.nodeName.toLowerCase()]&&i.push(o)}for(r=i.length;r--;)!(o=i[r]).hasChildNodes()||o.firstChild===o.lastChild&&""===o.firstChild.nodeValue?e.remove(o):(a=o)&&"A"===a.nodeName&&0===It.trim(_i(a.innerText||a.textContent)).length&&e.remove(o);var a}}(C,w,r),g=C,(h=c).normalize(),(v=h.lastChild)&&!/^(left|right)$/gi.test(g.getStyle(v,"float",!0))||g.add(h,"br"),C.isEmpty(c)&&sC(c),r.normalize(),C.isEmpty(r)?(C.remove(r),k()):Qb(a,r)),C.setAttrib(r,"id",""),a.fire("NewBlock",{newBlock:r})))},gC=function(e,t){return eC(e).filter(function(e){return 0<t.length&&Pr.is(Vn.fromDom(e),t)}).isSome()},hC=function(e){return gC(e,Lu(e))},vC=function(e){return gC(e,Iu(e))},yC=nf([{br:[]},{block:[]},{none:[]}]),bC=function(e,t){return vC(e)},CC=function(n){return function(e,t){return""===Ou(e)===n}},xC=function(n){return function(e,t){return nC(e)===n}},wC=function(n,r){return function(e,t){return tC(e)===n.toUpperCase()===r}},NC=function(e){return wC("pre",e)},EC=function(n){return function(e,t){return Du(e)===n}},SC=function(e,t){return hC(e)},kC=function(e,t){return t},TC=function(e){var t=Ou(e),n=Zb(e.dom,e.selection.getStart());return n&&e.schema.isValidChild(n.nodeName,t||"P")},AC=function(e,t){return function(n,r){return H.foldl(e,function(e,t){return e&&t(n,r)},!0)?A.some(t):A.none()}},RC=function(e,t){return Df([AC([bC],yC.none()),AC([wC("summary",!0)],yC.br()),AC([NC(!0),EC(!1),kC],yC.br()),AC([NC(!0),EC(!1)],yC.block()),AC([NC(!0),EC(!0),kC],yC.block()),AC([NC(!0),EC(!0)],yC.br()),AC([xC(!0),kC],yC.br()),AC([xC(!0)],yC.block()),AC([CC(!0),kC,TC],yC.block()),AC([CC(!0)],yC.br()),AC([SC],yC.br()),AC([CC(!1),kC],yC.br()),AC([TC],yC.block())],[e,t.shiftKey]).getOr(yC.none())},_C=function(e,t){RC(e,t).fold(function(){vm(e,t)},function(){pC(e,t)},V.noop)},BC=function(o){o.on("keydown",function(e){var t,n,r;e.keyCode===sh.ENTER&&(t=o,(n=e).isDefaultPrevented()||(n.preventDefault(),(r=t.undoManager).typing&&(r.typing=!1,r.add()),t.undoManager.transact(function(){!1===t.selection.isCollapsed()&&t.execCommand("Delete"),_C(t,n)})))})},DC=function(e,t,n){return u=t,!(!OC(n)||!Oo.isText(u.container())||(r=e,i=(o=t).container(),a=o.offset(),i.insertData(a,"\xa0"),r.selection.setCursorLocation(i,a+1),0));var r,o,i,a,u},OC=function(e){return e.fold(V.constant(!1),V.constant(!0),V.constant(!0),V.constant(!1))},PC=function(e){return!!e.selection.isCollapsed()&&(t=e,n=V.curry(xl.isInlineTarget,t),r=La.fromRangeStart(t.selection.getRng()),Gf(n,t.getBody(),r).map(V.curry(DC,t,r)).getOr(!1));var t,n,r},LC=function(r){r.on("keydown",function(e){var t,n;!1===e.isDefaultPrevented()&&(t=r,n=e,jb([{keyCode:sh.SPACEBAR,action:Hb(PC,t)}],n).each(function(e){n.preventDefault()}))})},IC=function(e,t){var n;t.hasAttribute("data-mce-caret")&&(Vi(t),(n=e).selection.setRng(n.selection.getRng()),e.selection.scrollIntoView(t))},MC=function(e,t){var n,r=(n=e,Tl(Vn.fromDom(n.getBody()),"*[data-mce-caret]").fold(V.constant(null),function(e){return e.dom()}));if(r)return"compositionstart"===t.type?(t.preventDefault(),t.stopPropagation(),void IC(e,r)):void(Ii(r)&&(IC(e,r),e.undoManager.add()))},FC=function(e){e.on("keyup compositionstart",V.curry(MC,e))},zC=function(e){var t=sd.setupSelectedState(e);FC(e),$b(e,t),Gb(e,t),BC(e),LC(e)};function UC(u){var s,n,r,o=It.each,c=sh.BACKSPACE,l=sh.DELETE,f=u.dom,d=u.selection,e=u.settings,t=u.parser,i=ve.gecko,a=ve.ie,m=ve.webkit,p="data:text/mce-internal,",g=a?"Text":"URL",h=function(e,t){try{u.getDoc().execCommand(e,!1,t)}catch(n){}},v=function(e){return e.isDefaultPrevented()},y=function(){u.shortcuts.add("meta+a",null,"SelectAll")},b=function(){u.on("keydown",function(e){if(!v(e)&&e.keyCode===c&&d.isCollapsed()&&0===d.getRng().startOffset){var t=d.getNode().previousSibling;if(t&&t.nodeName&&"table"===t.nodeName.toLowerCase())return e.preventDefault(),!1}})},C=function(){u.inline||(u.contentStyles.push("body {min-height: 150px}"),u.on("click",function(e){var t;if("HTML"===e.target.nodeName){if(11<ve.ie)return void u.getBody().focus();t=u.selection.getRng(),u.getBody().focus(),u.selection.setRng(t),u.selection.normalize(),u.nodeChanged()}}))};return u.on("keydown",function(e){var t,n,r,o,i;if(!v(e)&&e.keyCode===sh.BACKSPACE&&(n=(t=d.getRng()).startContainer,r=t.startOffset,o=f.getRoot(),i=n,t.collapsed&&0===r)){for(;i&&i.parentNode&&i.parentNode.firstChild===i&&i.parentNode!==o;)i=i.parentNode;"BLOCKQUOTE"===i.tagName&&(u.formatter.toggle("blockquote",null,i),(t=f.createRng()).setStart(n,0),t.setEnd(n,0),d.setRng(t))}}),s=function(e){var t=f.create("body"),n=e.cloneContents();return t.appendChild(n),d.serializer.serialize(t,{format:"html"})},u.on("keydown",function(e){var t,n,r,o,i,a=e.keyCode;if(!v(e)&&(a===l||a===c)){if(t=u.selection.isCollapsed(),n=u.getBody(),t&&!f.isEmpty(n))return;if(!t&&(r=u.selection.getRng(),o=s(r),(i=f.createRng()).selectNode(u.getBody()),o!==s(i)))return;e.preventDefault(),u.setContent(""),n.firstChild&&f.isBlock(n.firstChild)?u.selection.setCursorLocation(n.firstChild,0):u.selection.setCursorLocation(n,0),u.nodeChanged()}}),ve.windowsPhone||u.on("keyup focusin mouseup",function(e){sh.modifierPressed(e)||d.normalize()},!0),m&&(u.settings.content_editable||f.bind(u.getDoc(),"mousedown mouseup",function(e){var t;if(e.target===u.getDoc().documentElement)if(t=d.getRng(),u.getBody().focus(),"mousedown"===e.type){if(Li(t.startContainer))return;d.placeCaretAt(e.clientX,e.clientY)}else d.setRng(t)}),u.on("click",function(e){var t=e.target;/^(IMG|HR)$/.test(t.nodeName)&&"false"!==f.getContentEditableParent(t)&&(e.preventDefault(),u.selection.select(t),u.nodeChanged()),"A"===t.nodeName&&f.hasClass(t,"mce-item-anchor")&&(e.preventDefault(),d.select(t))}),e.forced_root_block&&u.on("init",function(){h("DefaultParagraphSeparator",e.forced_root_block)}),u.on("init",function(){u.dom.bind(u.getBody(),"submit",function(e){e.preventDefault()})}),b(),t.addNodeFilter("br",function(e){for(var t=e.length;t--;)"Apple-interchange-newline"===e[t].attr("class")&&e[t].remove()}),ve.iOS?(u.inline||u.on("keydown",function(){document.activeElement===document.body&&u.getWin().focus()}),C(),u.on("click",function(e){var t=e.target;do{if("A"===t.tagName)return void e.preventDefault()}while(t=t.parentNode)}),u.contentStyles.push(".mce-content-body {-webkit-touch-callout: none}")):y()),11<=ve.ie&&(C(),b()),ve.ie&&(y(),h("AutoUrlDetect",!1),u.on("dragstart",function(e){var t,n,r;(t=e).dataTransfer&&(u.selection.isCollapsed()&&"IMG"===t.target.tagName&&d.select(t.target),0<(n=u.selection.getContent()).length&&(r=p+escape(u.id)+","+escape(n),t.dataTransfer.setData(g,r)))}),u.on("drop",function(e){if(!v(e)){var t=(i=e).dataTransfer&&(a=i.dataTransfer.getData(g))&&0<=a.indexOf(p)?(a=a.substr(p.length).split(","),{id:unescape(a[0]),html:unescape(a[1])}):null;if(t&&t.id!==u.id){e.preventDefault();var n=Zy(e.x,e.y,u.getDoc());d.setRng(n),r=t.html,o=!0,u.queryCommandSupported("mceInsertClipboardContent")?u.execCommand("mceInsertClipboardContent",!1,{content:r,internal:o}):u.execCommand("mceInsertContent",!1,r)}}var r,o,i,a})),i&&(u.on("keydown",function(e){if(!v(e)&&e.keyCode===c){if(!u.getBody().getElementsByTagName("hr").length)return;if(d.isCollapsed()&&0===d.getRng().startOffset){var t=d.getNode(),n=t.previousSibling;if("HR"===t.nodeName)return f.remove(t),void e.preventDefault();n&&n.nodeName&&"hr"===n.nodeName.toLowerCase()&&(f.remove(n),e.preventDefault())}}}),Range.prototype.getClientRects||u.on("mousedown",function(e){if(!v(e)&&"HTML"===e.target.nodeName){var t=u.getBody();t.blur(),we.setEditorTimeout(u,function(){t.focus()})}}),n=function(){var e=f.getAttribs(d.getStart().cloneNode(!1));return function(){var t=d.getStart();t!==u.getBody()&&(f.setAttrib(t,"style",null),o(e,function(e){t.setAttributeNode(e.cloneNode(!0))}))}},r=function(){return!d.isCollapsed()&&f.getParent(d.getStart(),f.isBlock)!==f.getParent(d.getEnd(),f.isBlock)},u.on("keypress",function(e){var t;if(!v(e)&&(8===e.keyCode||46===e.keyCode)&&r())return t=n(),u.getDoc().execCommand("delete",!1,null),t(),e.preventDefault(),!1}),f.bind(u.getDoc(),"cut",function(e){var t;!v(e)&&r()&&(t=n(),we.setEditorTimeout(u,function(){t()}))}),e.readonly||u.on("BeforeExecCommand MouseDown",function(){h("StyleWithCSS",!1),h("enableInlineTableEditing",!1),e.object_resizing||h("enableObjectResizing",!1)}),u.on("SetContent ExecCommand",function(e){"setcontent"!==e.type&&"mceInsertLink"!==e.command||o(f.select("a"),function(e){var t=e.parentNode,n=f.getRoot();if(t.lastChild===e){for(;t&&!f.isBlock(t);){if(t.parentNode.lastChild!==t||t===n)return;t=t.parentNode}f.add(t,"br",{"data-mce-bogus":1})}})}),u.contentStyles.push("img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}"),ve.mac&&u.on("keydown",function(e){!sh.metaKeyPressed(e)||e.shiftKey||37!==e.keyCode&&39!==e.keyCode||(e.preventDefault(),u.selection.getSel().modify("move",37===e.keyCode?"backward":"forward","lineboundary"))}),b()),{refreshContentEditable:function(){},isHidden:function(){var e;return!i||u.removed?0:!(e=u.selection.getSel())||!e.rangeCount||0===e.rangeCount}}}var qC=function(e){return Oo.isElement(e)&&ho(Vn.fromDom(e))},VC=function(t){t.on("click",function(e){3===e.detail&&function(e){var t=e.selection.getRng(),n=Da.fromRangeStart(t),r=Da.fromRangeEnd(t);if(Da.isElementPosition(n)){var o=n.container();qC(o)&&Qa.firstPositionIn(o).each(function(e){return t.setStart(e.container(),e.offset())})}Da.isElementPosition(r)&&(o=n.container(),qC(o)&&Qa.lastPositionIn(o).each(function(e){return t.setEnd(e.container(),e.offset())})),e.selection.setRng(Zc(t))}(t)})},HC=function(e){var t,n;(t=e).on("click",function(e){t.dom.getParent(e.target,"details")&&e.preventDefault()}),(n=e).parser.addNodeFilter("details",function(e){H.each(e,function(e){e.attr("data-mce-open",e.attr("open")),e.attr("open","open")})}),n.serializer.addNodeFilter("details",function(e){H.each(e,function(e){var t=e.attr("data-mce-open");e.attr("open",k.isString(t)?t:null),e.attr("data-mce-open",null)})})},jC=vi.DOM,$C=function(e){var t;e.bindPendingEventDelegates(),e.initialized=!0,e.fire("init"),e.focus(!0),e.nodeChanged({initial:!0}),e.execCallback("init_instance_callback",e),(t=e).settings.auto_focus&&we.setEditorTimeout(t,function(){var e;(e=!0===t.settings.auto_focus?t:t.editorManager.get(t.settings.auto_focus)).destroyed||e.focus()},100)},WC=function(t,e){var n,r,u,o,i,a,s,c,l,f=t.settings,d=t.getElement(),m=t.getDoc();f.inline||(t.getElement().style.visibility=t.orgVisibility),e||f.content_editable||(m.open(),m.write(t.iframeHTML),m.close()),f.content_editable&&(t.on("remove",function(){var e=this.getBody();jC.removeClass(e,"mce-content-body"),jC.removeClass(e,"mce-edit-focus"),jC.setAttrib(e,"contentEditable",null)}),jC.addClass(d,"mce-content-body"),t.contentDocument=m=f.content_document||document,t.contentWindow=f.content_window||window,t.bodyElement=d,f.content_document=f.content_window=null,f.root_name=d.nodeName.toLowerCase()),(n=t.getBody()).disabled=!0,t.readonly=f.readonly,t.readonly||(t.inline&&"static"===jC.getStyle(n,"position",!0)&&(n.style.position="relative"),n.contentEditable=t.getParam("content_editable_state",!0)),n.disabled=!1,t.editorUpload=wg(t),t.schema=oi(f),t.dom=vi(m,{keep_values:!0,url_converter:t.convertURL,url_converter_scope:t,hex_colors:f.force_hex_style_colors,class_filter:f.class_filter,update_styles:!0,root_element:t.inline?t.getBody():null,collect:f.content_editable,schema:t.schema,onSetAttrib:function(e){t.fire("SetAttrib",e)}}),t.parser=((o=qy((u=t).settings,u.schema)).addAttributeFilter("src,href,style,tabindex",function(e,t){for(var n,r,o,i=e.length,a=u.dom;i--;)if(r=(n=e[i]).attr(t),o="data-mce-"+t,!n.attributes.map[o]){if(0===r.indexOf("data:")||0===r.indexOf("blob:"))continue;"style"===t?((r=a.serializeStyle(a.parseStyle(r),n.name)).length||(r=null),n.attr(o,r),n.attr(t,r)):"tabindex"===t?(n.attr(o,r),n.attr(t,null)):n.attr(o,u.convertURL(r,t,n.name))}}),o.addNodeFilter("script",function(e){for(var t,n,r=e.length;r--;)0!==(n=(t=e[r]).attr("type")||"no/type").indexOf("mce-")&&t.attr("type","mce-"+n)}),o.addNodeFilter("#cdata",function(e){for(var t,n=e.length;n--;)(t=e[n]).type=8,t.name="#comment",t.value="[CDATA["+t.value+"]]"}),o.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(e){for(var t,n=e.length,r=u.schema.getNonEmptyElements();n--;)(t=e[n]).isEmpty(r)&&0===t.getAll("br").length&&(t.append(new _y("br",1)).shortEnded=!0)}),o),t.serializer=Wy(f,t),t.selection=Bb(t.dom,t.getWin(),t.serializer,t),t.formatter=vy(t),t.undoManager=Uh(t),t._nodeChangeDispatcher=new Dg(t),t._selectionOverrides=ph(t),HC(t),VC(t),zC(t),kg(t),t.fire("PreInit"),f.browser_spellcheck||f.gecko_spellcheck||(m.body.spellcheck=!1,jC.setAttrib(n,"spellcheck","false")),t.quirks=UC(t),t.fire("PostRender"),f.directionality&&(n.dir=f.directionality),f.nowrap&&(n.style.whiteSpace="nowrap"),f.protect&&t.on("BeforeSetContent",function(t){It.each(f.protect,function(e){t.content=t.content.replace(e,function(e){return"\x3c!--mce:protected "+escape(e)+"--\x3e"})})}),t.on("SetContent",function(){t.addVisual(t.getBody())}),t.load({initial:!0,format:"html"}),t.startContent=t.getContent({format:"raw"}),t.on("compositionstart compositionend",function(e){t.composing="compositionstart"===e.type}),0<t.contentStyles.length&&(r="",It.each(t.contentStyles,function(e){r+=e+"\r\n"}),t.dom.addStyle(r)),(i=t,i.inline?jC.styleSheetLoader:i.dom.styleSheetLoader).loadAll(t.contentCSS,function(e){$C(t)},function(e){$C(t)}),f.content_style&&(a=t,s=f.content_style,c=Vn.fromDom(a.getDoc().head),l=Vn.fromTag("style"),lr.set(l,"type","text/css"),Hu.append(l,Vn.fromText(s)),Hu.append(c,l))},KC=vi.DOM,XC=function(e,t){var n,r,o,i,a,u,s,c=e.editorManager.translate("Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help"),l=(n=e.id,r=c,o=t.height,i=ku(e),s=Vn.fromTag("iframe"),lr.setAll(s,i),lr.setAll(s,{id:n+"_ifr",frameBorder:"0",allowTransparency:"true",title:r}),yr(s,{width:"100%",height:(a=o,u="number"==typeof a?a+"px":a,u||""),display:"block"}),s).dom();l.onload=function(){l.onload=null,e.fire("load")};var f,d,m,p,g=function(e,t){if(document.domain!==window.location.hostname&&ve.ie&&ve.ie<12){var n=xg.uuid("mce");e[n]=function(){WC(e)};var r='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinymce.get("'+e.id+'");document.write(ed.iframeHTML);document.close();ed.'+n+"(true);})()";return KC.setAttrib(t,"src",r),!0}return!1}(e,l);return e.contentAreaContainer=t.iframeContainer,e.iframeElement=l,e.iframeHTML=(p=Tu(f=e)+"<html><head>",Au(f)!==f.documentBaseUrl&&(p+='<base href="'+f.documentBaseURI.getURI()+'" />'),p+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />',d=Ru(f),m=_u(f),Bu(f)&&(p+='<meta http-equiv="Content-Security-Policy" content="'+Bu(f)+'" />'),p+='</head><body id="'+d+'" class="mce-content-body '+m+'" data-id="'+f.id+'"><br></body></html>'),KC.add(t.iframeContainer,l),g},YC=function(e,t){var n=XC(e,t);t.editorContainer&&(KC.get(t.editorContainer).style.display=e.orgDisplay,e.hidden=KC.isHidden(t.editorContainer)),e.getElement().style.display="none",KC.setAttrib(e.id,"aria-hidden","true"),n||WC(e)},GC=vi.DOM,JC=function(t,n,e){var r,o,i=og.get(e);if(r=og.urls[e]||t.documentBaseUrl.replace(/\/$/,""),e=It.trim(e),i&&-1===It.inArray(n,e)){if(It.each(og.dependencies(e),function(e){JC(t,n,e)}),t.plugins[e])return;o=new i(t,r,t.$),(t.plugins[e]=o).init&&(o.init(t,r),n.push(e))}},QC=function(e){return e.replace(/^\-/,"")},ZC=function(e){return{editorContainer:e,iframeContainer:e}},ex=function(e){var t,n,r=e.getElement();return e.inline?ZC(null):(t=r,n=GC.create("div"),GC.insertAfter(n,t),ZC(n))},tx=function(e){var t,n,r,o,i,a,u,s,c,l,f,d=e.settings,m=e.getElement();return e.orgDisplay=m.style.display,k.isString(d.theme)?(l=(o=e).settings,f=o.getElement(),i=l.width||GC.getStyle(f,"width")||"100%",a=l.height||GC.getStyle(f,"height")||f.offsetHeight,u=l.min_height||100,(s=/^[0-9\.]+(|px)$/i).test(""+i)&&(i=Math.max(parseInt(i,10),100)),s.test(""+a)&&(a=Math.max(parseInt(a,10),u)),c=o.theme.renderUI({targetNode:f,width:i,height:a,deltaWidth:l.delta_width,deltaHeight:l.delta_height}),l.content_editable||(a=(c.iframeHeight||a)+("number"==typeof a?c.deltaHeight||0:""))<u&&(a=u),c.height=a,c):k.isFunction(d.theme)?(r=(t=e).getElement(),(n=t.settings.theme(t,r)).editorContainer.nodeType&&(n.editorContainer.id=n.editorContainer.id||t.id+"_parent"),n.iframeContainer&&n.iframeContainer.nodeType&&(n.iframeContainer.id=n.iframeContainer.id||t.id+"_iframecontainer"),n.height=n.iframeHeight?n.iframeHeight:r.offsetHeight,n):ex(e)},nx=function(t){var e,n,r,o,i,a,u=t.settings,s=t.getElement();return t.rtl=u.rtl_ui||t.editorManager.i18n.rtl,t.editorManager.i18n.setCode(u.language),u.aria_label=u.aria_label||GC.getAttrib(s,"aria-label",t.getLang("aria.rich_text_area")),t.fire("ScriptsLoaded"),o=(n=t).settings.theme,k.isString(o)?(n.settings.theme=QC(o),r=ig.get(o),n.theme=new r(n,ig.urls[o]),n.theme.init&&n.theme.init(n,ig.urls[o]||n.documentBaseUrl.replace(/\/$/,""),n.$)):n.theme={},i=t,a=[],It.each(i.settings.plugins.split(/[ ,]/),function(e){JC(i,a,QC(e))}),e=tx(t),t.editorContainer=e.editorContainer?e.editorContainer:null,u.content_css&&It.each(It.explode(u.content_css),function(e){t.contentCSS.push(t.documentBaseURI.toAbsolute(e))}),u.content_editable?WC(t):YC(t,e)},rx=vi.DOM,ox=function(e){return"-"===e.charAt(0)},ix=function(i,a){var u=wi.ScriptLoader;!function(e,t,n,r){var o=t.settings,i=o.theme;if(k.isString(i)){if(!ox(i)&&!ig.urls.hasOwnProperty(i)){var a=o.theme_url;a?ig.load(i,t.documentBaseURI.toAbsolute(a)):ig.load(i,"themes/"+i+"/theme"+n+".js")}e.loadQueue(function(){ig.waitFor(i,r)})}else r()}(u,i,a,function(){var e,t,n,r,o;e=u,(n=(t=i).settings).language&&"en"!==n.language&&!n.language_url&&(n.language_url=t.editorManager.baseURL+"/langs/"+n.language+".js"),n.language_url&&!t.editorManager.i18n.data[n.language]&&e.add(n.language_url),r=i.settings,o=a,It.isArray(r.plugins)&&(r.plugins=r.plugins.join(" ")),It.each(r.external_plugins,function(e,t){og.load(t,e),r.plugins+=" "+t}),It.each(r.plugins.split(/[ ,]/),function(e){if((e=It.trim(e))&&!og.urls[e])if(ox(e)){e=e.substr(1,e.length);var t=og.dependencies(e);It.each(t,function(e){var t={prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"};e=og.createUrl(t,e),og.load(e.resource,e)})}else og.load(e,{prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"})}),u.loadQueue(function(){i.removed||nx(i)},i,function(e){eg(i,e[0]),i.removed||nx(i)})})},ax=function(t){var e=t.settings,n=t.id,r=function(){rx.unbind(window,"ready",r),t.render()};if(Be.Event.domLoaded){if(t.getElement()&&ve.contentEditable){e.inline?t.inline=!0:(t.orgVisibility=t.getElement().style.visibility,t.getElement().style.visibility="hidden");var o=t.getElement().form||rx.getParent(n,"form");o&&(t.formElement=o,e.hidden_input&&!/TEXTAREA|INPUT/i.test(t.getElement().nodeName)&&(rx.insertAfter(rx.create("input",{type:"hidden",name:n}),n),t.hasHiddenInput=!0),t.formEventDelegate=function(e){t.fire(e.type,e)},rx.bind(o,"submit reset",t.formEventDelegate),t.on("reset",function(){t.setContent(t.startContent,{format:"raw"})}),!e.submit_patch||o.submit.nodeType||o.submit.length||o._mceOldSubmit||(o._mceOldSubmit=o.submit,o.submit=function(){return t.editorManager.triggerSave(),t.setDirty(!1),o._mceOldSubmit(o)})),t.windowManager=Yp(t),t.notificationManager=Xp(t),"xml"===e.encoding&&t.on("GetContent",function(e){e.save&&(e.content=rx.encode(e.content))}),e.add_form_submit_trigger&&t.on("submit",function(){t.initialized&&t.save()}),e.add_unload_trigger&&(t._beforeUnload=function(){!t.initialized||t.destroyed||t.isHidden()||t.save({format:"raw",no_events:!0,set_dirty:!1})},t.editorManager.on("BeforeUnload",t._beforeUnload)),t.editorManager.add(t),ix(t,t.suffix)}}else rx.bind(window,"ready",r)},ux=function(e,t,n){var r=e.sidebars?e.sidebars:[];r.push({name:t,settings:n}),e.sidebars=r},sx=It.each,cx=It.trim,lx="source protocol authority userInfo user password host port relative path directory file query anchor".split(" "),fx={ftp:21,http:80,https:443,mailto:25},dx=function(r,e){var t,n,o=this;if(r=cx(r),t=(e=o.settings=e||{}).base_uri,/^([\w\-]+):([^\/]{2})/i.test(r)||/^\s*#/.test(r))o.source=r;else{var i=0===r.indexOf("//");0!==r.indexOf("/")||i||(r=(t&&t.protocol||"http")+"://mce_host"+r),/^[\w\-]*:?\/\//.test(r)||(n=e.base_uri?e.base_uri.path:new dx(document.location.href).directory,""==e.base_uri.protocol?r="//mce_host"+o.toAbsPath(n,r):(r=/([^#?]*)([#?]?.*)/.exec(r),r=(t&&t.protocol||"http")+"://mce_host"+o.toAbsPath(n,r[1])+r[2])),r=r.replace(/@@/g,"(mce_at)"),r=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(r),sx(lx,function(e,t){var n=r[t];n&&(n=n.replace(/\(mce_at\)/g,"@@")),o[e]=n}),t&&(o.protocol||(o.protocol=t.protocol),o.userInfo||(o.userInfo=t.userInfo),o.port||"mce_host"!==o.host||(o.port=t.port),o.host&&"mce_host"!==o.host||(o.host=t.host),o.source=""),i&&(o.protocol="")}};dx.prototype={setPath:function(e){e=/^(.*?)\/?(\w+)?$/.exec(e),this.path=e[0],this.directory=e[1],this.file=e[2],this.source="",this.getURI()},toRelative:function(e){var t;if("./"===e)return e;if("mce_host"!==(e=new dx(e,{base_uri:this})).host&&this.host!==e.host&&e.host||this.port!==e.port||this.protocol!==e.protocol&&""!==e.protocol)return e.getURI();var n=this.getURI(),r=e.getURI();return n===r||"/"===n.charAt(n.length-1)&&n.substr(0,n.length-1)===r?n:(t=this.toRelPath(this.path,e.path),e.query&&(t+="?"+e.query),e.anchor&&(t+="#"+e.anchor),t)},toAbsolute:function(e,t){return(e=new dx(e,{base_uri:this})).getURI(t&&this.isSameOrigin(e))},isSameOrigin:function(e){if(this.host==e.host&&this.protocol==e.protocol){if(this.port==e.port)return!0;var t=fx[this.protocol];if(t&&(this.port||t)==(e.port||t))return!0}return!1},toRelPath:function(e,t){var n,r,o,i=0,a="";if(e=(e=e.substring(0,e.lastIndexOf("/"))).split("/"),n=t.split("/"),e.length>=n.length)for(r=0,o=e.length;r<o;r++)if(r>=n.length||e[r]!==n[r]){i=r+1;break}if(e.length<n.length)for(r=0,o=n.length;r<o;r++)if(r>=e.length||e[r]!==n[r]){i=r+1;break}if(1===i)return t;for(r=0,o=e.length-(i-1);r<o;r++)a+="../";for(r=i-1,o=n.length;r<o;r++)a+=r!==i-1?"/"+n[r]:n[r];return a},toAbsPath:function(e,t){var n,r,o,i=0,a=[];for(r=/\/$/.test(t)?"/":"",e=e.split("/"),t=t.split("/"),sx(e,function(e){e&&a.push(e)}),e=a,n=t.length-1,a=[];0<=n;n--)0!==t[n].length&&"."!==t[n]&&(".."!==t[n]?0<i?i--:a.push(t[n]):i++);return 0!==(o=(n=e.length-i)<=0?a.reverse().join("/"):e.slice(0,n).join("/")+"/"+a.reverse().join("/")).indexOf("/")&&(o="/"+o),r&&o.lastIndexOf("/")!==o.length-1&&(o+=r),o},getURI:function(e){var t,n=this;return n.source&&!e||(t="",e||(n.protocol?t+=n.protocol+"://":t+="//",n.userInfo&&(t+=n.userInfo+"@"),n.host&&(t+=n.host),n.port&&(t+=":"+n.port)),n.path&&(t+=n.path),n.query&&(t+="?"+n.query),n.anchor&&(t+="#"+n.anchor),n.source=t),n.source}},dx.parseDataUri=function(e){var t,n;return e=decodeURIComponent(e).split(","),(n=/data:([^;]+)/.exec(e[0]))&&(t=n[1]),{type:t,data:e[1]}},dx.getDocumentBaseUrl=function(e){var t;return t=0!==e.protocol.indexOf("http")&&"file:"!==e.protocol?e.href:e.protocol+"//"+e.host+e.pathname,/^[^:]+:\/\/\/?[^\/]+\//.test(t)&&(t=t.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(t)||(t+="/")),t};var mx=function(e,t,n){var r,o,i,a,u;if(t.format=t.format?t.format:"html",t.get=!0,t.getInner=!0,t.no_events||e.fire("BeforeGetContent",t),"raw"===t.format)r=It.trim(bh.trimExternal(e.serializer,n.innerHTML));else if("text"===t.format)r=_i(n.innerText||n.textContent);else{if("tree"===t.format)return e.serializer.serialize(n,t);i=(o=e).serializer.serialize(n,t),a=Ou(o),u=new RegExp("^(<"+a+"[^>]*>( | |\\s|\xa0|<br \\/>|)<\\/"+a+">[\r\n]*|<br \\/>[\r\n]*)$"),r=i.replace(u,"")}return"text"===t.format||wo(Vn.fromDom(n))?t.content=r:t.content=It.trim(r),t.no_events||e.fire("GetContent",t),t.content},px=function(e,t){t(e),e.firstChild&&px(e.firstChild,t),e.next&&px(e.next,t)},gx=function(e,t,n){var r=function(e,n,t){var r={},o={},i=[];for(var a in t.firstChild&&px(t.firstChild,function(t){H.each(e,function(e){e.name===t.name&&(r[e.name]?r[e.name].nodes.push(t):r[e.name]={filter:e,nodes:[t]})}),H.each(n,function(e){"string"==typeof t.attr(e.name)&&(o[e.name]?o[e.name].nodes.push(t):o[e.name]={filter:e,nodes:[t]})})}),r)r.hasOwnProperty(a)&&i.push(r[a]);for(var u in o)o.hasOwnProperty(u)&&i.push(o[u]);return i}(e,t,n);H.each(r,function(t){H.each(t.filter.callbacks,function(e){e(t.nodes,t.filter.name,{})})})},hx=function(e){return e instanceof _y},vx=function(e,t){var r;e.dom.setHTML(e.getBody(),t),zp(r=e)&&Qa.firstPositionIn(r.getBody()).each(function(e){var t=e.getNode(),n=Oo.isTable(t)?Qa.firstPositionIn(t).getOr(e):e;r.selection.setRng(n.toRange())})},yx=function(u,s,c){return void 0===c&&(c={}),c.format=c.format?c.format:"html",c.set=!0,c.content=hx(s)?"":s,hx(s)||c.no_events||(u.fire("BeforeSetContent",c),s=c.content),A.from(u.getBody()).fold(V.constant(s),function(e){return hx(s)?function(e,t,n,r){gx(e.parser.getNodeFilters(),e.parser.getAttributeFilters(),n);var o=Jc({validate:e.validate},e.schema).serialize(n);return r.content=wo(Vn.fromDom(t))?o:It.trim(o),vx(e,r.content),r.no_events||e.fire("SetContent",r),n}(u,e,s,c):(t=u,n=e,o=c,0===(r=s).length||/^\s+$/.test(r)?(a='<br data-mce-bogus="1">',"TABLE"===n.nodeName?r="<tr><td>"+a+"</td></tr>":/^(UL|OL)$/.test(n.nodeName)&&(r="<li>"+a+"</li>"),(i=Ou(t))&&t.schema.isValidChild(n.nodeName.toLowerCase(),i.toLowerCase())?(r=a,r=t.dom.createHTML(i,t.settings.forced_root_block_attrs,r)):r||(r='<br data-mce-bogus="1">'),vx(t,r),t.fire("SetContent",o)):("raw"!==o.format&&(r=Jc({validate:t.validate},t.schema).serialize(t.parser.parse(r,{isRootContent:!0,insert:!0}))),o.content=wo(Vn.fromDom(n))?r:It.trim(r),vx(t,o.content),o.no_events||t.fire("SetContent",o)),o.content);var t,n,r,o,i,a})},bx=vi.DOM,Cx=function(e){return A.from(e).each(function(e){return e.destroy()})},xx=function(e){if(!e.removed){var t=e._selectionOverrides,n=e.editorUpload,r=e.getBody(),o=e.getElement();r&&e.save(),e.removed=!0,e.unbindAllNativeEvents(),e.hasHiddenInput&&o&&bx.remove(o.nextSibling),!e.inline&&r&&(i=e,bx.setStyle(i.id,"display",i.orgDisplay)),fp(e),e.editorManager.remove(e),bx.remove(e.getContainer()),Cx(t),Cx(n),e.destroy()}var i},wx=function(e,t){var n,r,o,i=e.selection,a=e.dom;e.destroyed||(t||e.removed?(t||(e.editorManager.off("beforeunload",e._beforeUnload),e.theme&&e.theme.destroy&&e.theme.destroy(),Cx(i),Cx(a)),(r=(n=e).formElement)&&(r._mceOldSubmit&&(r.submit=r._mceOldSubmit,r._mceOldSubmit=null),bx.unbind(r,"submit reset",n.formEventDelegate)),(o=e).contentAreaContainer=o.formElement=o.container=o.editorContainer=null,o.bodyElement=o.contentDocument=o.contentWindow=null,o.iframeElement=o.targetElm=null,o.selection&&(o.selection=o.selection.win=o.selection.dom=o.selection.dom.doc=null),e.destroyed=!0):e.remove())},Nx=vi.DOM,Ex=It.extend,Sx=It.each,kx=It.resolve,Tx=ve.ie,Ax=function(e,t,n){var r,o,i,a,u,s,c,l=this,f=l.documentBaseUrl=n.documentBaseURL,d=n.baseURI;r=l,o=e,i=f,a=n.defaultSettings,u=t,c={id:o,theme:"modern",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:i,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"<!DOCTYPE html>",visual:!0,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",forced_root_block:"p",hidden_input:!0,render_ui:!0,indentation:"30px",inline_styles:!0,convert_fonts_to_spans:!0,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",entity_encoding:"named",url_converter:(s=r).convertURL,url_converter_scope:s,ie7_compat:!0},t=gl(cl,c,a,u),l.settings=t,Si.language=t.language||"en",Si.languageLoad=t.language_load,Si.baseURL=n.baseURL,l.id=e,l.setDirty(!1),l.plugins={},l.documentBaseURI=new dx(t.document_base_url,{base_uri:d}),l.baseURI=d,l.contentCSS=[],l.contentStyles=[],l.shortcuts=new Ap(l),l.loadedCSS={},l.editorCommands=new Hm(l),l.suffix=n.suffix,l.editorManager=n,l.inline=t.inline,l.buttons={},l.menuItems={},t.cache_suffix&&(ve.cacheSuffix=t.cache_suffix.replace(/^[\?\&]+/,"")),!1===t.override_viewport&&(ve.overrideViewPort=!1),n.fire("SetupEditor",{editor:l}),l.execCallback("setup",l),l.$=tn.overrideDefaults(function(){return{context:l.inline?l.getBody():l.getDoc(),element:l.getBody()}})};Ex(Ax.prototype={render:function(){ax(this)},focus:function(e){Fp(this,e)},hasFocus:function(){return zp(this)},execCallback:function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r,o=this.settings[e];if(o)return this.callbackLookup&&(r=this.callbackLookup[e])&&(o=r.func,r=r.scope),"string"==typeof o&&(r=(r=o.replace(/\.\w+$/,""))?kx(r):0,o=kx(o),this.callbackLookup=this.callbackLookup||{},this.callbackLookup[e]={func:o,scope:r}),o.apply(r||this,Array.prototype.slice.call(arguments,1))},translate:function(e){if(e&&It.is(e,"string")){var n=this.settings.language||"en",r=this.editorManager.i18n;e=r.data[n+"."+e]||e.replace(/\{\#([^\}]+)\}/g,function(e,t){return r.data[n+"."+t]||"{#"+t+"}"})}return this.editorManager.translate(e)},getLang:function(e,t){return this.editorManager.i18n.data[(this.settings.language||"en")+"."+e]||(t!==undefined?t:"{#"+e+"}")},getParam:function(e,t,n){return yl(this,e,t,n)},nodeChanged:function(e){this._nodeChangeDispatcher.nodeChanged(e)},addButton:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),t.stateSelector&&"undefined"==typeof t.active&&(t.active=!1),t.text||t.icon||(t.icon=e),n.buttons=n.buttons,t.tooltip=t.tooltip||t.title,n.buttons[e]=t},addSidebar:function(e,t){return ux(this,e,t)},addMenuItem:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),n.menuItems=n.menuItems,n.menuItems[e]=t},addContextToolbar:function(e,t){var n,r=this;r.contextToolbars=r.contextToolbars||[],"string"==typeof e&&(n=e,e=function(e){return r.dom.is(e,n)}),r.contextToolbars.push({id:xg.uuid("mcet"),predicate:e,items:t})},addCommand:function(e,t,n){this.editorCommands.addCommand(e,t,n)},addQueryStateHandler:function(e,t,n){this.editorCommands.addQueryStateHandler(e,t,n)},addQueryValueHandler:function(e,t,n){this.editorCommands.addQueryValueHandler(e,t,n)},addShortcut:function(e,t,n,r){this.shortcuts.add(e,t,n,r)},execCommand:function(e,t,n,r){return this.editorCommands.execCommand(e,t,n,r)},queryCommandState:function(e){return this.editorCommands.queryCommandState(e)},queryCommandValue:function(e){return this.editorCommands.queryCommandValue(e)},queryCommandSupported:function(e){return this.editorCommands.queryCommandSupported(e)},show:function(){this.hidden&&(this.hidden=!1,this.inline?this.getBody().contentEditable=!0:(Nx.show(this.getContainer()),Nx.hide(this.id)),this.load(),this.fire("show"))},hide:function(){var e=this,t=e.getDoc();e.hidden||(Tx&&t&&!e.inline&&t.execCommand("SelectAll"),e.save(),e.inline?(e.getBody().contentEditable=!1,e===e.editorManager.focusedEditor&&(e.editorManager.focusedEditor=null)):(Nx.hide(e.getContainer()),Nx.setStyle(e.id,"display",e.orgDisplay)),e.hidden=!0,e.fire("hide"))},isHidden:function(){return!!this.hidden},setProgressState:function(e,t){this.fire("ProgressState",{state:e,time:t})},load:function(e){var t,n=this.getElement();return this.removed?"":n?((e=e||{}).load=!0,t=this.setContent(n.value!==undefined?n.value:n.innerHTML,e),e.element=n,e.no_events||this.fire("LoadContent",e),e.element=n=null,t):void 0},save:function(e){var t,n,r=this,o=r.getElement();if(o&&r.initialized&&!r.removed)return(e=e||{}).save=!0,e.element=o,e.content=r.getContent(e),e.no_events||r.fire("SaveContent",e),"raw"===e.format&&r.fire("RawSaveContent",e),t=e.content,/TEXTAREA|INPUT/i.test(o.nodeName)?o.value=t:(r.inline||(o.innerHTML=t),(n=Nx.getParent(r.id,"form"))&&Sx(n.elements,function(e){if(e.name===r.id)return e.value=t,!1})),e.element=o=null,!1!==e.set_dirty&&r.setDirty(!1),t},setContent:function(e,t){return yx(this,e,t)},getContent:function(e){return t=this,void 0===(n=e)&&(n={}),A.from(t.getBody()).fold(V.constant("tree"===n.format?new _y("body",11):""),function(e){return mx(t,n,e)});var t,n},insertContent:function(e,t){t&&(e=Ex({content:e},t)),this.execCommand("mceInsertContent",!1,e)},isDirty:function(){return!this.isNotDirty},setDirty:function(e){var t=!this.isNotDirty;this.isNotDirty=!e,e&&e!==t&&this.fire("dirty")},setMode:function(e){var t,n;(n=e)!==vp(t=this)&&(t.initialized?hp(t,"readonly"===n):t.on("init",function(){hp(t,"readonly"===n)}),dp(t,n))},getContainer:function(){return this.container||(this.container=Nx.get(this.editorContainer||this.id+"_parent")),this.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return this.targetElm||(this.targetElm=Nx.get(this.id)),this.targetElm},getWin:function(){var e;return this.contentWindow||(e=this.iframeElement)&&(this.contentWindow=e.contentWindow),this.contentWindow},getDoc:function(){var e;return this.contentDocument||(e=this.getWin())&&(this.contentDocument=e.document),this.contentDocument},getBody:function(){var e=this.getDoc();return this.bodyElement||(e?e.body:null)},convertURL:function(e,t,n){var r=this.settings;return r.urlconverter_callback?this.execCallback("urlconverter_callback",e,n,!0,t):!r.convert_urls||n&&"LINK"===n.nodeName||0===e.indexOf("file:")||0===e.length?e:r.relative_urls?this.documentBaseURI.toRelative(e):e=this.documentBaseURI.toAbsolute(e,r.remove_script_host)},addVisual:function(e){var n,r=this,o=r.settings,i=r.dom;e=e||r.getBody(),r.hasVisual===undefined&&(r.hasVisual=o.visual),Sx(i.select("table,a",e),function(e){var t;switch(e.nodeName){case"TABLE":return n=o.visual_table_class||"mce-item-table",void((t=i.getAttrib(e,"border"))&&"0"!==t||!r.hasVisual?i.removeClass(e,n):i.addClass(e,n));case"A":return void(i.getAttrib(e,"href")||(t=i.getAttrib(e,"name")||e.id,n=o.visual_anchor_class||"mce-item-anchor",t&&r.hasVisual?i.addClass(e,n):i.removeClass(e,n)))}}),r.fire("VisualAid",{element:e,hasVisual:r.hasVisual})},remove:function(){xx(this)},destroy:function(e){wx(this,e)},uploadImages:function(e){return this.editorUpload.uploadImages(e)},_scanForImages:function(){return this.editorUpload.scanForImages()}},Np);var Rx,_x,Bx,Dx={isEditorUIElement:function(e){return-1!==e.className.toString().indexOf("mce-")}},Ox=function(n,e){var t,r;Un.detect().browser.isIE()?(r=n).on("focusout",function(){Lm(r)}):(t=e,n.on("mouseup touchend",function(e){t.throttle()})),n.on("keyup nodechange",function(e){var t;"nodechange"===(t=e).type&&t.selectionChange||Lm(n)})},Px=function(e){var t,n,r,o=ah(function(){Lm(e)},0);e.inline&&(t=e,n=o,r=function(){n.throttle()},vi.DOM.bind(document,"mouseup",r),t.on("remove",function(){vi.DOM.unbind(document,"mouseup",r)})),e.on("init",function(){Ox(e,o)}),e.on("remove",function(){o.cancel()})},Lx=vi.DOM,Ix=function(e){return Dx.isEditorUIElement(e)},Mx=function(t,e){var n=t?t.settings.custom_ui_selector:"";return null!==Lx.getParent(e,function(e){return Ix(e)||!!n&&t.dom.is(e,n)})},Fx=function(r,e){var t=e.editor;Px(t),t.on("focusin",function(){var e=r.focusedEditor;e!==this&&(e&&e.fire("blur",{focusedEditor:this}),r.setActive(this),(r.focusedEditor=this).fire("focus",{blurredEditor:e}),this.focus(!0))}),t.on("focusout",function(){var t=this;we.setEditorTimeout(t,function(){var e=r.focusedEditor;Mx(t,function(){try{return document.activeElement}catch(e){return document.body}}())||e!==t||(t.fire("blur",{focusedEditor:null}),r.focusedEditor=null)})}),Rx||(Rx=function(e){var t,n=r.activeEditor;t=e.target,n&&t.ownerDocument===document&&(t===document.body||Mx(n,t)||r.focusedEditor!==n||(n.fire("blur",{focusedEditor:null}),r.focusedEditor=null))},Lx.bind(document,"focusin",Rx))},zx=function(e,t){e.focusedEditor===t.editor&&(e.focusedEditor=null),e.activeEditor||(Lx.unbind(document,"focusin",Rx),Rx=null)},Ux=function(e){e.on("AddEditor",V.curry(Fx,e)),e.on("RemoveEditor",V.curry(zx,e))},qx={},Vx="en",Hx={setCode:function(e){e&&(Vx=e,this.rtl=!!this.data[e]&&"rtl"===this.data[e]._dir)},getCode:function(){return Vx},rtl:!1,add:function(e,t){var n=qx[e];for(var r in n||(qx[e]=n={}),t)n[r]=t[r];this.setCode(e)},translate:function(e){var t=qx[Vx]||{},n=function(e){return It.is(e,"function")?Object.prototype.toString.call(e):r(e)?"":""+e},r=function(e){return""===e||null===e||It.is(e,"undefined")},o=function(e){return e=n(e),It.hasOwn(t,e)?n(t[e]):e};if(r(e))return"";if(It.is(e,"object")&&It.hasOwn(e,"raw"))return n(e.raw);if(It.is(e,"array")){var i=e.slice(1);e=o(e[0]).replace(/\{([0-9]+)\}/g,function(e,t){return It.hasOwn(i,t)?n(i[t]):e})}return o(e).replace(/{context:\w+}$/,"")},data:qx},jx=vi.DOM,$x=It.explode,Wx=It.each,Kx=It.extend,Xx=0,Yx=!1,Gx=[],Jx=[],Qx=function(t){Wx(Bx.get(),function(e){"scroll"===t.type?e.fire("ScrollWindow",t):e.fire("ResizeWindow",t)})},Zx=function(e){e!==Yx&&(e?tn(window).on("resize scroll",Qx):tn(window).off("resize scroll",Qx),Yx=e)},ew=function(t){var e=Jx;delete Gx[t.id];for(var n=0;n<Gx.length;n++)if(Gx[n]===t){Gx.splice(n,1);break}return Jx=H.filter(Jx,function(e){return t!==e}),Bx.activeEditor===t&&(Bx.activeEditor=0<Jx.length?Jx[0]:null),Bx.focusedEditor===t&&(Bx.focusedEditor=null),e.length!==Jx.length};Kx(Bx={defaultSettings:{},$:tn,majorVersion:"4",minorVersion:"7.13",releaseDate:"2018-05-16",editors:Gx,i18n:Hx,activeEditor:null,settings:{},setup:function(){var e,t,n,r,o="";if(t=dx.getDocumentBaseUrl(document.location),/^[^:]+:\/\/\/?[^\/]+\//.test(t)&&(t=t.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(t)||(t+="/")),n=window.tinymce||window.tinyMCEPreInit)e=n.base||n.baseURL,o=n.suffix;else{for(var i=document.getElementsByTagName("script"),a=0;a<i.length;a++){var u=(r=i[a].src).substring(r.lastIndexOf("/"));if(/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(r)){-1!==u.indexOf(".min")&&(o=".min"),e=r.substring(0,r.lastIndexOf("/"));break}}!e&&document.currentScript&&(-1!==(r=document.currentScript.src).indexOf(".min")&&(o=".min"),e=r.substring(0,r.lastIndexOf("/")))}this.baseURL=new dx(t).toAbsolute(e),this.documentBaseURL=t,this.baseURI=new dx(this.baseURL),this.suffix=o,Ux(this)},overrideDefaults:function(e){var t,n;(t=e.base_url)&&(this.baseURL=new dx(this.documentBaseURL).toAbsolute(t.replace(/\/+$/,"")),this.baseURI=new dx(this.baseURL)),n=e.suffix,e.suffix&&(this.suffix=n);var r=(this.defaultSettings=e).plugin_base_urls;for(var o in r)Si.PluginManager.urls[o]=r[o]},init:function(r){var n,u,s=this;u=It.makeMap("area base basefont br col frame hr img input isindex link meta param embed source wbr track colgroup option tbody tfoot thead tr script noscript style textarea video audio iframe object menu"," ");var c=function(e){var t=e.id;return t||(t=(t=e.name)&&!jx.get(t)?e.name:jx.uniqueId(),e.setAttribute("id",t)),t},l=function(e,t){return t.constructor===RegExp?t.test(e.className):jx.hasClass(e,t)},f=function(e){n=e},e=function(){var o,i=0,a=[],n=function(e,t,n){var r=new Ax(e,t,s);a.push(r),r.on("init",function(){++i===o.length&&f(a)}),r.targetElm=r.targetElm||n,r.render()};jx.unbind(window,"ready",e),function(e){var t=r[e];t&&t.apply(s,Array.prototype.slice.call(arguments,2))}("onpageload"),o=tn.unique(function(t){var e,n=[];if(ve.ie&&ve.ie<11)return rg("TinyMCE does not support the browser you are using. For a list of supported browsers please see: https://www.tinymce.com/docs/get-started/system-requirements/"),[];if(t.types)return Wx(t.types,function(e){n=n.concat(jx.select(e.selector))}),n;if(t.selector)return jx.select(t.selector);if(t.target)return[t.target];switch(t.mode){case"exact":0<(e=t.elements||"").length&&Wx($x(e),function(t){var e;(e=jx.get(t))?n.push(e):Wx(document.forms,function(e){Wx(e.elements,function(e){e.name===t&&(t="mce_editor_"+Xx++,jx.setAttrib(e,"id",t),n.push(e))})})});break;case"textareas":case"specific_textareas":Wx(jx.select("textarea"),function(e){t.editor_deselector&&l(e,t.editor_deselector)||t.editor_selector&&!l(e,t.editor_selector)||n.push(e)})}return n}(r)),r.types?Wx(r.types,function(t){It.each(o,function(e){return!jx.is(e,t.selector)||(n(c(e),Kx({},r,t),e),!1)})}):(It.each(o,function(e){var t;(t=s.get(e.id))&&t.initialized&&!(t.getContainer()||t.getBody()).parentNode&&(ew(t),t.unbindAllNativeEvents(),t.destroy(!0),t.removed=!0,t=null)}),0===(o=It.grep(o,function(e){return!s.get(e.id)})).length?f([]):Wx(o,function(e){var t;t=e,r.inline&&t.tagName.toLowerCase()in u?rg("Could not initialize inline editor on invalid inline target element",e):n(c(e),r,e)}))};return s.settings=r,jx.bind(window,"ready",e),new ye(function(t){n?t(n):f=function(e){t(e)}})},get:function(t){return 0===arguments.length?Jx.slice(0):k.isString(t)?H.find(Jx,function(e){return e.id===t}).getOr(null):k.isNumber(t)&&Jx[t]?Jx[t]:null},add:function(e){var t=this;return Gx[e.id]===e||(null===t.get(e.id)&&("length"!==e.id&&(Gx[e.id]=e),Gx.push(e),Jx.push(e)),Zx(!0),t.activeEditor=e,t.fire("AddEditor",{editor:e}),_x||(_x=function(){t.fire("BeforeUnload")},jx.bind(window,"beforeunload",_x))),e},createEditor:function(e,t){return this.add(new Ax(e,t,this))},remove:function(e){var t,n,r=this;if(e)return k.isString(e)?(e=e.selector||e,void Wx(jx.select(e),function(e){(n=r.get(e.id))&&r.remove(n)})):(n=e,k.isNull(r.get(n.id))?null:(ew(n)&&r.fire("RemoveEditor",{editor:n}),0===Jx.length&&jx.unbind(window,"beforeunload",_x),n.remove(),Zx(0<Jx.length),n));for(t=Jx.length-1;0<=t;t--)r.remove(Jx[t])},execCommand:function(e,t,n){var r=this.get(n);switch(e){case"mceAddEditor":return this.get(n)||new Ax(n,this.settings,this).render(),!0;case"mceRemoveEditor":return r&&r.remove(),!0;case"mceToggleEditor":return r?r.isHidden()?r.show():r.hide():this.execCommand("mceAddEditor",0,n),!0}return!!this.activeEditor&&this.activeEditor.execCommand(e,t,n)},triggerSave:function(){Wx(Jx,function(e){e.save()})},addI18n:function(e,t){Hx.add(e,t)},translate:function(e){return Hx.translate(e)},setActive:function(e){var t=this.activeEditor;this.activeEditor!==e&&(t&&t.fire("deactivate",{relatedTarget:e}),e.fire("activate",{relatedTarget:t})),this.activeEditor=e}},Xm),Bx.setup();var tw,nw=Bx;function rw(n){return{walk:function(e,t){return Bv(n,e,t)},split:mv,normalize:function(t){return um(n,t).fold(V.constant(!1),function(e){return t.setStart(e.startContainer,e.startOffset),t.setEnd(e.endContainer,e.endOffset),!0})}}}(tw=rw||(rw={})).compareRanges=em,tw.getCaretRangeFromPoint=Zy,tw.getSelectedNode=aa,tw.getNode=ua;var ow,iw,aw=rw,uw=Math.min,sw=Math.max,cw=Math.round,lw=function(e,t,n){var r,o,i,a,u,s;return r=t.x,o=t.y,i=e.w,a=e.h,u=t.w,s=t.h,"b"===(n=(n||"").split(""))[0]&&(o+=s),"r"===n[1]&&(r+=u),"c"===n[0]&&(o+=cw(s/2)),"c"===n[1]&&(r+=cw(u/2)),"b"===n[3]&&(o-=a),"r"===n[4]&&(r-=i),"c"===n[3]&&(o-=cw(a/2)),"c"===n[4]&&(r-=cw(i/2)),fw(r,o,i,a)},fw=function(e,t,n,r){return{x:e,y:t,w:n,h:r}},dw={inflate:function(e,t,n){return fw(e.x-t,e.y-n,e.w+2*t,e.h+2*n)},relativePosition:lw,findBestRelativePosition:function(e,t,n,r){var o,i;for(i=0;i<r.length;i++)if((o=lw(e,t,r[i])).x>=n.x&&o.x+o.w<=n.w+n.x&&o.y>=n.y&&o.y+o.h<=n.h+n.y)return r[i];return null},intersect:function(e,t){var n,r,o,i;return n=sw(e.x,t.x),r=sw(e.y,t.y),o=uw(e.x+e.w,t.x+t.w),i=uw(e.y+e.h,t.y+t.h),o-n<0||i-r<0?null:fw(n,r,o-n,i-r)},clamp:function(e,t,n){var r,o,i,a,u,s,c,l,f,d;return u=e.x,s=e.y,c=e.x+e.w,l=e.y+e.h,f=t.x+t.w,d=t.y+t.h,r=sw(0,t.x-u),o=sw(0,t.y-s),i=sw(0,c-f),a=sw(0,l-d),u+=r,s+=o,n&&(c+=r,l+=o,u-=i,s-=a),fw(u,s,(c-=i)-u,(l-=a)-s)},create:fw,fromClientRect:function(e){return fw(e.left,e.top,e.width,e.height)}},mw={},pw={add:function(e,t){mw[e.toLowerCase()]=t},has:function(e){return!!mw[e.toLowerCase()]},get:function(e){var t=e.toLowerCase(),n=mw.hasOwnProperty(t)?mw[t]:null;if(null===n)throw new Error("Could not find module for type: "+e);return n},create:function(e,t){var n;if("string"==typeof e?(t=t||{}).type=e:e=(t=e).type,e=e.toLowerCase(),!(n=mw[e]))throw new Error("Could not find control by type: "+e);return(n=new n(t)).type=e,n}},gw=It.each,hw=It.extend,vw=function(){};vw.extend=ow=function(n){var e,t,r,o=this.prototype,i=function(){var e,t,n;if(!iw&&(this.init&&this.init.apply(this,arguments),t=this.Mixins))for(e=t.length;e--;)(n=t[e]).init&&n.init.apply(this,arguments)},a=function(){return this},u=function(n,r){return function(){var e,t=this._super;return this._super=o[n],e=r.apply(this,arguments),this._super=t,e}};for(t in iw=!0,e=new this,iw=!1,n.Mixins&&(gw(n.Mixins,function(e){for(var t in e)"init"!==t&&(n[t]=e[t])}),o.Mixins&&(n.Mixins=o.Mixins.concat(n.Mixins))),n.Methods&&gw(n.Methods.split(","),function(e){n[e]=a}),n.Properties&&gw(n.Properties.split(","),function(e){var t="_"+e;n[e]=function(e){return e!==undefined?(this[t]=e,this):this[t]}}),n.Statics&&gw(n.Statics,function(e,t){i[t]=e}),n.Defaults&&o.Defaults&&(n.Defaults=hw({},o.Defaults,n.Defaults)),n)"function"==typeof(r=n[t])&&o[t]?e[t]=u(t,r):e[t]=r;return i.prototype=e,(i.constructor=i).extend=ow,i};var yw=Math.min,bw=Math.max,Cw=Math.round,xw=function(e,n){var r,o,t,i;if(n=n||'"',null===e)return"null";if("string"==(t=typeof e))return o="\bb\tt\nn\ff\rr\"\"''\\\\",n+e.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(e,t){return'"'===n&&"'"===e?e:(r=o.indexOf(t))+1?"\\"+o.charAt(r+1):(e=t.charCodeAt().toString(16),"\\u"+"0000".substring(e.length)+e)})+n;if("object"===t){if(e.hasOwnProperty&&"[object Array]"===Object.prototype.toString.call(e)){for(r=0,o="[";r<e.length;r++)o+=(0<r?",":"")+xw(e[r],n);return o+"]"}for(i in o="{",e)e.hasOwnProperty(i)&&(o+="function"!=typeof e[i]?(1<o.length?","+n:n)+i+n+":"+xw(e[i],n):"");return o+"}"}return""+e},ww={serialize:xw,parse:function(e){try{return JSON.parse(e)}catch(t){}}},Nw={callbacks:{},count:0,send:function(t){var n=this,r=vi.DOM,o=t.count!==undefined?t.count:n.count,i="tinymce_jsonp_"+o;n.callbacks[o]=function(e){r.remove(i),delete n.callbacks[o],t.callback(e)},r.add(r.doc.body,"script",{id:i,src:t.url,type:"text/javascript"}),n.count++}},Ew={send:function(e){var t,n=0,r=function(){!e.async||4===t.readyState||1e4<n++?(e.success&&n<1e4&&200===t.status?e.success.call(e.success_scope,""+t.responseText,t,e):e.error&&e.error.call(e.error_scope,1e4<n?"TIMED_OUT":"GENERAL",t,e),t=null):setTimeout(r,10)};if(e.scope=e.scope||this,e.success_scope=e.success_scope||e.scope,e.error_scope=e.error_scope||e.scope,e.async=!1!==e.async,e.data=e.data||"",Ew.fire("beforeInitialize",{settings:e}),t=new ag){if(t.overrideMimeType&&t.overrideMimeType(e.content_type),t.open(e.type||(e.data?"POST":"GET"),e.url,e.async),e.crossDomain&&(t.withCredentials=!0),e.content_type&&t.setRequestHeader("Content-Type",e.content_type),e.requestheaders&&It.each(e.requestheaders,function(e){t.setRequestHeader(e.key,e.value)}),t.setRequestHeader("X-Requested-With","XMLHttpRequest"),(t=Ew.fire("beforeSend",{xhr:t,settings:e}).xhr).send(e.data),!e.async)return r();setTimeout(r,10)}}};It.extend(Ew,Xm);var Sw=It.extend,kw=function(e){this.settings=Sw({},e),this.count=0};kw.sendRPC=function(e){return(new kw).send(e)},kw.prototype={send:function(n){var r=n.error,o=n.success;(n=Sw(this.settings,n)).success=function(e,t){void 0===(e=ww.parse(e))&&(e={error:"JSON Parse error."}),e.error?r.call(n.error_scope||n.scope,e.error,t):o.call(n.success_scope||n.scope,e.result)},n.error=function(e,t){r&&r.call(n.error_scope||n.scope,e,t)},n.data=ww.serialize({id:n.id||"c"+this.count++,method:n.method,params:n.params}),n.content_type="application/json",Ew.send(n)}};var Tw,Aw=window.localStorage,Rw=nw,_w={geom:{Rect:dw},util:{Promise:ye,Delay:we,Tools:It,VK:sh,URI:dx,Class:vw,EventDispatcher:$m,Observable:Xm,I18n:Hx,XHR:Ew,JSON:ww,JSONRequest:kw,JSONP:Nw,LocalStorage:Aw,Color:function(e){var n={},u=0,s=0,c=0,t=function(e){var t;return"object"==typeof e?"r"in e?(u=e.r,s=e.g,c=e.b):"v"in e&&function(e,t,n){var r,o,i,a;if(e=(parseInt(e,10)||0)%360,t=parseInt(t,10)/100,n=parseInt(n,10)/100,t=bw(0,yw(t,1)),n=bw(0,yw(n,1)),0!==t){switch(r=e/60,i=(o=n*t)*(1-Math.abs(r%2-1)),a=n-o,Math.floor(r)){case 0:u=o,s=i,c=0;break;case 1:u=i,s=o,c=0;break;case 2:u=0,s=o,c=i;break;case 3:u=0,s=i,c=o;break;case 4:u=i,s=0,c=o;break;case 5:u=o,s=0,c=i;break;default:u=s=c=0}u=Cw(255*(u+a)),s=Cw(255*(s+a)),c=Cw(255*(c+a))}else u=s=c=Cw(255*n)}(e.h,e.s,e.v):(t=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(e))?(u=parseInt(t[1],10),s=parseInt(t[2],10),c=parseInt(t[3],10)):(t=/#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(e))?(u=parseInt(t[1],16),s=parseInt(t[2],16),c=parseInt(t[3],16)):(t=/#([0-F])([0-F])([0-F])/gi.exec(e))&&(u=parseInt(t[1]+t[1],16),s=parseInt(t[2]+t[2],16),c=parseInt(t[3]+t[3],16)),u=u<0?0:255<u?255:u,s=s<0?0:255<s?255:s,c=c<0?0:255<c?255:c,n};return e&&t(e),n.toRgb=function(){return{r:u,g:s,b:c}},n.toHsv=function(){return e=u,t=s,n=c,o=0,(i=yw(e/=255,yw(t/=255,n/=255)))===(a=bw(e,bw(t,n)))?{h:0,s:0,v:100*(o=i)}:(r=(a-i)/a,{h:Cw(60*((e===i?3:n===i?1:5)-(e===i?t-n:n===i?e-t:n-e)/((o=a)-i))),s:Cw(100*r),v:Cw(100*o)});var e,t,n,r,o,i,a},n.toHex=function(){var e=function(e){return 1<(e=parseInt(e,10).toString(16)).length?e:"0"+e};return"#"+e(u)+e(s)+e(c)},n.parse=t,n}},dom:{EventUtils:Be,Sizzle:mt,DomQuery:tn,TreeWalker:ao,DOMUtils:vi,ScriptLoader:wi,RangeUtils:aw,Serializer:Wy,ControlSelection:Jy,BookmarkManager:Xy,Selection:Bb,Event:Be.Event},html:{Styles:ai,Entities:Ko,Node:_y,Schema:oi,SaxParser:vh,DomParser:qy,Writer:Gc,Serializer:Jc},ui:{Factory:pw},Env:ve,AddOnManager:Si,Formatter:vy,UndoManager:Uh,EditorCommands:Hm,WindowManager:Yp,NotificationManager:Xp,EditorObservable:Np,Shortcuts:Ap,Editor:Ax,FocusManager:Dx,EditorManager:nw,DOM:vi.DOM,ScriptLoader:wi.ScriptLoader,PluginManager:Si.PluginManager,ThemeManager:Si.ThemeManager,trim:It.trim,isArray:It.isArray,is:It.is,toArray:It.toArray,makeMap:It.makeMap,each:It.each,map:It.map,grep:It.grep,inArray:It.inArray,extend:It.extend,create:It.create,walk:It.walk,createNS:It.createNS,resolve:It.resolve,explode:It.explode,_addCacheSuffix:It._addCacheSuffix,isOpera:ve.opera,isWebKit:ve.webkit,isIE:ve.ie,isGecko:ve.gecko,isMac:ve.mac},Bw=Rw=It.extend(Rw,_w);Tw=Bw,window.tinymce=Tw,window.tinyMCE=Tw,function(e){if("object"==typeof module)try{module.exports=e}catch(t){}}(Bw)}(); \ No newline at end of file diff --git a/groups.io/tinymce-5.10.9/tinymce.min.js b/groups.io/tinymce-5.10.9/tinymce.min.js new file mode 100644 index 00000000..b251deb0 --- /dev/null +++ b/groups.io/tinymce-5.10.9/tinymce.min.js @@ -0,0 +1,9 @@ +/** + * Copyright (c) Tiny Technologies, Inc. All rights reserved. + * Licensed under the LGPL or a commercial license. + * For LGPL see License.txt in the project root for license information. + * For commercial licenses see https://www.tiny.cloud/ + * + * Version: 5.10.9 (2023-11-15) + */ +!function(){"use strict";function r(e){if(null===e)return"null";if(void 0===e)return"undefined";var t=typeof e;return"object"==t&&(Array.prototype.isPrototypeOf(e)||e.constructor&&"Array"===e.constructor.name)?"array":"object"==t&&(String.prototype.isPrototypeOf(e)||e.constructor&&"String"===e.constructor.name)?"string":t}function f(o){return m(function(e,t){if(e.length!==t.length)return!1;for(var n=e.length,r=0;r<n;r++)if(!o.eq(e[r],t[r]))return!1;return!0})}function d(l){return m(function(e,t){var n,r,o,i=Object.keys(e),a=Object.keys(t);if(r=f(g),o=function(e){return t=n,Array.prototype.slice.call(e).sort(t);var t},!m(function(e,t){return r.eq(o(e),o(t))}).eq(i,a))return!1;for(var u=i.length,s=0;s<u;s++){var c=i[s];if(!l.eq(e[c],t[c]))return!1}return!0})}function e(r){return function(e){return n=typeof(t=e),(null===t?"null":"object"==n&&(Array.prototype.isPrototypeOf(t)||t.constructor&&"Array"===t.constructor.name)?"array":"object"==n&&(String.prototype.isPrototypeOf(t)||t.constructor&&"String"===t.constructor.name)?"string":n)===r;var t,n}}function t(t){return function(e){return typeof e===t}}function n(t){return function(e){return t===e}}function K(e){return null==e}function V(e){return!K(e)}function te(){}function i(n,r){return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return n(r.apply(null,e))}}function a(t,n){return function(e){return t(n(e))}}function J(e){return function(){return e}}function u(e){return e}function o(e,t){return e===t}var m=function(e){return{eq:e}},g=m(function(e,t){return e===t}),p=m(function(e,t){if(e===t)return!0;var n=r(e);return n===r(t)&&(-1!==["undefined","boolean","number","string","function","xml","null"].indexOf(n)?e===t:"array"===n?f(p).eq(e,t):"object"===n&&d(p).eq(e,t))}),X=e("string"),h=e("object"),S=e("array"),l=n(null),v=t("boolean"),b=n(void 0),y=t("function"),N=t("number");function R(r){for(var o=[],e=1;e<arguments.length;e++)o[e-1]=arguments[e];return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=o.concat(e);return r.apply(null,n)}}function s(t){return function(e){return!t(e)}}function C(e){return e()}function x(e){e()}function c(){return E}var D=J(!1),w=J(!0),E={fold:function(e,t){return e()},isSome:D,isNone:w,getOr:u,getOrThunk:k,getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:J(null),getOrUndefined:J(void 0),or:u,orThunk:k,map:c,each:te,bind:c,exists:D,forall:w,filter:function(){return E},toArray:function(){return[]},toString:J("none()")};function k(e){return e()}function _(e,t){return ye.call(e,t)}function T(e,t){return-1<_(e,t)}function F(e,t){for(var n=0,r=e.length;n<r;n++)if(t(e[n],n))return!0;return!1}function A(e,t){for(var n=e.length,r=new Array(n),o=0;o<n;o++){var i=e[o];r[o]=t(i,o)}return r}function Y(e,t){for(var n=0,r=e.length;n<r;n++)t(e[n],n)}function O(e,t){for(var n=e.length-1;0<=n;n--)t(e[n],n)}function B(e,t){for(var n=[],r=[],o=0,i=e.length;o<i;o++){var a=e[o];(t(a,o)?n:r).push(a)}return{pass:n,fail:r}}function U(e,t){for(var n=[],r=0,o=e.length;r<o;r++){var i=e[r];t(i,r)&&n.push(i)}return n}function P(e,n,r){return O(e,function(e,t){r=n(r,e,t)}),r}function L(e,n,r){return Y(e,function(e,t){r=n(r,e,t)}),r}function I(e,t,n){for(var r=0,o=e.length;r<o;r++){var i=e[r];if(t(i,r))return ve.some(i);if(n(i,r))break}return ve.none()}function M(e,t){return I(e,t,D)}function z(e,t){for(var n=0,r=e.length;n<r;n++)if(t(e[n],n))return ve.some(n);return ve.none()}function H(e,t){return function(e){for(var t=[],n=0,r=e.length;n<r;++n){if(!S(e[n]))throw new Error("Arr.flatten item "+n+" was not an array, input: "+e);Ce.apply(t,e[n])}return t}(A(e,t))}function j(e,t){for(var n=0,r=e.length;n<r;++n)if(!0!==t(e[n],n))return!1;return!0}function q(e){var t=be.call(e,0);return t.reverse(),t}function $(e,t){return U(e,function(e){return!T(t,e)})}function W(e,t){var n=be.call(e,0);return n.sort(t),n}function G(e,t){return 0<=t&&t<e.length?ve.some(e[t]):ve.none()}function Q(e){return G(e,0)}function Z(e){return G(e,e.length-1)}function ee(e,t){for(var n=0;n<e.length;n++){var r=t(e[n],n);if(r.isSome())return r}return ve.none()}function ne(e,t){for(var n=we(e),r=0,o=n.length;r<o;r++){var i=n[r];t(e[i],i)}}function re(e,n){return Ne(e,function(e,t){return{k:t,v:n(e,t)}})}function oe(n){return function(e,t){n[t]=e}}function ie(e,n,r,o){return ne(e,function(e,t){(n(e,t)?r:o)(e,t)}),1}function ae(e,t){var n={};return ie(e,t,oe(n),te),n}function ue(e,t){return Ee(e,t)?ve.from(e[t]):ve.none()}function se(e,t){return Ee(e,t)&&void 0!==e[t]&&null!==e[t]}function ce(e,t,n){var r,o;if(!e)return!1;if(n=n||e,void 0!==e.length){for(r=0,o=e.length;r<o;r++)if(!1===t.call(n,e[r],r,e))return!1}else for(r in e)if(Ee(e,r)&&!1===t.call(n,e[r],r,e))return!1;return!0}function le(n,r){var o=[];return ce(n,function(e,t){o.push(r(e,t,n))}),o}function fe(n,r){var o=[];return ce(n,function(e,t){r&&!r(e,t,n)||o.push(e)}),o}function de(e,t){if(e)for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}function me(e,t,n,r){for(var o=b(n)?e[0]:n,i=0;i<e.length;i++)o=t.call(r,o,e[i],i);return o}function ge(e,t,n){for(var r=0,o=e.length;r<o;r++)if(t.call(n,e[r],r,e))return r;return-1}function pe(e){return e[e.length-1]}var he=function(n){function e(){return o}function t(e){return e(n)}var r=J(n),o={fold:function(e,t){return t(n)},isSome:w,isNone:D,getOr:r,getOrThunk:r,getOrDie:r,getOrNull:r,getOrUndefined:r,or:e,orThunk:e,map:function(e){return he(e(n))},each:function(e){e(n)},bind:t,exists:t,forall:t,filter:function(e){return e(n)?o:E},toArray:function(){return[n]},toString:function(){return"some("+n+")"}};return o},ve={some:he,none:c,from:function(e){return null==e?E:he(e)}},be=Array.prototype.slice,ye=Array.prototype.indexOf,Ce=Array.prototype.push,xe=y(Array.from)?Array.from:function(e){return be.call(e)},we=Object.keys,Se=Object.hasOwnProperty,Ne=function(e,r){var o={};return ne(e,function(e,t){var n=r(e,t);o[n.k]=n.v}),o},Ee=function(e,t){return Se.call(e,t)},ke=Array.isArray,_e=function(){return(_e=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var o in t=arguments[n])Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o]);return e}).apply(this,arguments)};function Ae(e,t,n){if(n||2===arguments.length)for(var r,o=0,i=t.length;o<i;o++)!r&&o in t||((r=r||Array.prototype.slice.call(t,0,o))[o]=t[o]);return e.concat(r||Array.prototype.slice.call(t))}function Re(n){var r,o=!1;return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return o||(o=!0,r=n.apply(null,e)),r}}function De(e,t){var n=String(t).toLowerCase();return M(e,function(e){return e.search(n)})}function Te(e,t){return-1!==e.indexOf(t)}function Oe(t){return function(e){return e.replace(t,"")}}function Be(e){return 0<e.length}function Pe(e){return!Be(e)}function Le(t){return function(e){return Te(e,t)}}function Ie(e){return window.matchMedia(e).matches}function Me(e){return null==e?"":(""+e).replace(wt,"")}function Fe(e,t){return t?!("array"!==t||!ke(e))||typeof e===t:void 0!==e}function Ue(e,t){for(var n=[],r=function(e){return n.push(e),t(e)},o=t(e);(o=o.bind(r)).isSome(););return n}function ze(e,t){var n=e.dom;if(1!==n.nodeType)return!1;var r=n;if(void 0!==r.matches)return r.matches(t);if(void 0!==r.msMatchesSelector)return r.msMatchesSelector(t);if(void 0!==r.webkitMatchesSelector)return r.webkitMatchesSelector(t);if(void 0!==r.mozMatchesSelector)return r.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}function He(e){return 1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType||0===e.childElementCount}function je(e,t){return e.dom===t.dom}function Ve(e,t){return dt().browser.isIE()?(n=e.dom,r=t.dom,o=Node.DOCUMENT_POSITION_CONTAINED_BY,0!=(n.compareDocumentPosition(r)&o)):(i=e.dom)!==(a=t.dom)&&i.contains(a);var n,r,o,i,a}function qe(){return Xe(0,0)}function $e(e){function t(e){return function(){return n===e}}var n=e.current,r=e.version;return{current:n,version:r,isEdge:t("Edge"),isChrome:t("Chrome"),isIE:t("IE"),isOpera:t("Opera"),isFirefox:t(nt),isSafari:t("Safari")}}function We(e){function t(e){return function(){return n===e}}var n=e.current,r=e.version;return{current:n,version:r,isWindows:t(it),isiOS:t("iOS"),isAndroid:t(at),isOSX:t("OSX"),isLinux:t("Linux"),isSolaris:t(ut),isFreeBSD:t(st),isChromeOS:t(ct)}}function Ke(e){if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}}var Xe=function(e,t){return{major:e,minor:t}},Ye={nu:Xe,detect:function(e,t){var n,r,o=String(t).toLowerCase();return 0===e.length?qe():(r=function(e,t){for(var n=0;n<e.length;n++){var r=e[n];if(r.test(t))return r}}(e,n=o))?Xe(i(1),i(2)):{major:0,minor:0};function i(e){return Number(n.replace(r,"$"+e))}},unknown:qe},Ge=function(e,t){return""===(n=t)||e.length>=n.length&&e.substr(0,0+n.length)===n;var n},Je=Oe(/^\s+|\s+$/g),Qe=Oe(/^\s+/g),Ze=Oe(/\s+$/g),et=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,tt={browsers:J([{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:function(e){return Te(e,"edge/")&&Te(e,"chrome")&&Te(e,"safari")&&Te(e,"applewebkit")}},{name:"Chrome",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,et],search:function(e){return Te(e,"chrome")&&!Te(e,"chromeframe")}},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:function(e){return Te(e,"msie")||Te(e,"trident")}},{name:"Opera",versionRegexes:[et,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:Le("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:Le("firefox")},{name:"Safari",versionRegexes:[et,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:function(e){return(Te(e,"safari")||Te(e,"mobile/"))&&Te(e,"applewebkit")}}]),oses:J([{name:"Windows",search:Le("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:function(e){return Te(e,"iphone")||Te(e,"ipad")},versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:Le("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"OSX",search:Le("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:Le("linux"),versionRegexes:[]},{name:"Solaris",search:Le("sunos"),versionRegexes:[]},{name:"FreeBSD",search:Le("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:Le("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}])},nt="Firefox",rt=function(){return $e({current:void 0,version:Ye.unknown()})},ot=$e,it=(J("Edge"),J("Chrome"),J("IE"),J("Opera"),J(nt),J("Safari"),"Windows"),at="Android",ut="Solaris",st="FreeBSD",ct="ChromeOS",lt=function(){return We({current:void 0,version:Ye.unknown()})},ft=We,dt=(J(it),J("iOS"),J(at),J("Linux"),J("OSX"),J(ut),J(st),J(ct),Re(function(){return e=navigator.userAgent,t=ve.from(navigator.userAgentData),n=Ie,p=tt.browsers(),h=tt.oses(),v=t.bind(function(e){return r=p,ee(e.brands,function(t){var n=t.brand.toLowerCase();return M(r,function(e){var t;return n===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())}).map(function(e){return{current:e.name,version:Ye.nu(parseInt(t.version,10),0)}})});var r}).orThunk(function(){return De(p,n=e).map(function(e){var t=Ye.detect(e.versionRegexes,n);return{current:e.name,version:t}});var n}).fold(rt,ot),b=De(h,r=e).map(function(e){var t=Ye.detect(e.versionRegexes,r);return{current:e.name,version:t}}).fold(lt,ft),{browser:v,os:b,deviceType:(i=v,a=e,u=n,s=(o=b).isiOS()&&!0===/ipad/i.test(a),c=o.isiOS()&&!s,f=(l=o.isiOS()||o.isAndroid())||u("(pointer:coarse)"),d=s||!c&&l&&u("(min-device-width:768px)"),m=c||l&&!d,g=i.isSafari()&&o.isiOS()&&!1===/safari/i.test(a),{isiPad:J(s),isiPhone:J(c),isTablet:J(d),isPhone:J(m),isTouch:J(f),isAndroid:o.isAndroid,isiOS:o.isiOS,isWebView:J(g),isDesktop:J(!m&&!d&&!g)})};var e,t,n,r,o,i,a,u,s,c,l,f,d,m,g,p,h,v,b})),mt=navigator.userAgent,gt=dt(),pt=gt.browser,ht=gt.os,vt=gt.deviceType,bt=/WebKit/.test(mt)&&!pt.isEdge(),yt="FormData"in window&&"FileReader"in window&&"URL"in window&&!!URL.createObjectURL,Ct=-1!==mt.indexOf("Windows Phone"),xt={opera:pt.isOpera(),webkit:bt,ie:!(!pt.isIE()&&!pt.isEdge())&&pt.version.major,gecko:pt.isFirefox(),mac:ht.isOSX()||ht.isiOS(),iOS:vt.isiPad()||vt.isiPhone(),android:ht.isAndroid(),contentEditable:!0,transparentSrc:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",caretAfter:!0,range:window.getSelection&&"Range"in window,documentMode:pt.isIE()?document.documentMode||7:10,fileApi:yt,ceFalse:!0,cacheSuffix:null,container:null,experimentalShadowDom:!1,canHaveCSP:!pt.isIE(),desktop:vt.isDesktop(),windowsPhone:Ct,browser:{current:pt.current,version:pt.version,isChrome:pt.isChrome,isEdge:pt.isEdge,isFirefox:pt.isFirefox,isIE:pt.isIE,isOpera:pt.isOpera,isSafari:pt.isSafari},os:{current:ht.current,version:ht.version,isAndroid:ht.isAndroid,isChromeOS:ht.isChromeOS,isFreeBSD:ht.isFreeBSD,isiOS:ht.isiOS,isLinux:ht.isLinux,isOSX:ht.isOSX,isSolaris:ht.isSolaris,isWindows:ht.isWindows},deviceType:{isDesktop:vt.isDesktop,isiPad:vt.isiPad,isiPhone:vt.isiPhone,isPhone:vt.isPhone,isTablet:vt.isTablet,isTouch:vt.isTouch,isWebView:vt.isWebView}},wt=/^\s*|\s*$/g,St=function(e,n,r,o){o=o||this,e&&ce(e=r?e[r]:e,function(e,t){return!1!==n.call(o,e,t,r)&&void St(e,n,r,o)})},Nt={trim:Me,isArray:ke,is:Fe,toArray:function(e){if(ke(e))return e;for(var t=[],n=0,r=e.length;n<r;n++)t[n]=e[n];return t},makeMap:function(e,t,n){var r;for(t=t||",",n=n||{},r=(e="string"==typeof(e=e||[])?e.split(t):e).length;r--;)n[e[r]]={};return n},each:ce,map:le,grep:fe,inArray:de,hasOwn:Ee,extend:function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];for(var r=0;r<t.length;r++){var o,i,a=t[r];for(o in a)!Ee(a,o)||void 0!==(i=a[o])&&(e[o]=i)}return e},create:function(e,t,n){var r,o,i,a=this,u=0,s=(e=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(e))[3].match(/(^|\.)(\w+)$/i)[2],c=a.createNS(e[3].replace(/\.\w+$/,""),n);if(!c[s]){if("static"===e[2])return c[s]=t,void(this.onCreate&&this.onCreate(e[2],e[3],c[s]));t[s]||(t[s]=function(){},u=1),c[s]=t[s],a.extend(c[s].prototype,t),e[5]&&(r=a.resolve(e[5]).prototype,o=e[5].match(/\.(\w+)$/i)[1],i=c[s],c[s]=u?function(){return r[o].apply(this,arguments)}:function(){return this.parent=r[o],i.apply(this,arguments)},c[s].prototype[s]=c[s],a.each(r,function(e,t){c[s].prototype[t]=r[t]}),a.each(t,function(e,t){r[t]?c[s].prototype[t]=function(){return this.parent=r[t],e.apply(this,arguments)}:t!==s&&(c[s].prototype[t]=e)})),a.each(t.static,function(e,t){c[s][t]=e})}},walk:St,createNS:function(e,t){var n,r;for(t=t||window,e=e.split("."),n=0;n<e.length;n++)t[r=e[n]]||(t[r]={}),t=t[r];return t},resolve:function(e,t){var n,r;for(t=t||window,n=0,r=(e=e.split(".")).length;n<r&&(t=t[e[n]]);n++);return t},explode:function(e,t){return!e||Fe(e,"array")?e:le(e.split(t||","),Me)},_addCacheSuffix:function(e){var t=xt.cacheSuffix;return t&&(e+=(-1===e.indexOf("?")?"?":"&")+t),e}},Et={fromHtml:function(e,t){var n=(t||document).createElement("div");if(n.innerHTML=e,!n.hasChildNodes()||1<n.childNodes.length)throw console.error("HTML does not have a single root node",e),new Error("HTML must have a single root node");return Ke(n.childNodes[0])},fromTag:function(e,t){var n=(t||document).createElement(e);return Ke(n)},fromText:function(e,t){var n=(t||document).createTextNode(e);return Ke(n)},fromDom:Ke,fromPoint:function(e,t,n){return ve.from(e.dom.elementFromPoint(t,n)).map(Ke)}};function kt(e){return e.dom.nodeName.toLowerCase()}function _t(e){return e.dom.nodeType}function At(t){return function(e){return _t(e)===t}}function Rt(e){return Et.fromDom(e.dom.ownerDocument)}function Dt(e){return Rn(e)?e:Rt(e)}function Tt(e){return Et.fromDom(Dt(e).dom.defaultView)}function Ot(e){return ve.from(e.dom.parentNode).map(Et.fromDom)}function Bt(e){return ve.from(e.dom.previousSibling).map(Et.fromDom)}function Pt(e){return ve.from(e.dom.nextSibling).map(Et.fromDom)}function Lt(e){return q(Ue(e,Bt))}function It(e){return Ue(e,Pt)}function Mt(e,t){var n=e.dom.childNodes;return ve.from(n[t]).map(Et.fromDom)}function Ft(e){return Mt(e,0)}function Ut(e){return Mt(e,e.dom.childNodes.length-1)}function zt(e){return e.dom.childNodes.length}function Ht(e){return Dn(e)&&V(e.dom.host)}function jt(t){return Ht(t)?t:function(){var e=Dt(t).dom.head;if(null==e)throw new Error("Head is not available yet");return Et.fromDom(e)}()}function Vt(e){return Et.fromDom(e.dom.host)}function qt(t,n){Ot(t).each(function(e){e.dom.insertBefore(n.dom,t.dom)})}function $t(e,t){Pt(e).fold(function(){Ot(e).each(function(e){Ln(e,t)})},function(e){qt(e,t)})}function Wt(t,n){Ft(t).fold(function(){Ln(t,n)},function(e){t.dom.insertBefore(n.dom,e.dom)})}function Kt(t,e){Y(e,function(e){Ln(t,e)})}function Xt(e){e.dom.textContent="",Y(Tn(e),function(e){In(e)})}function Yt(e){var t,n=Tn(e);0<n.length&&(t=e,Y(n,function(e){qt(t,e)})),In(e)}function Gt(e,t){return void 0!==e?e:void 0!==t?t:0}function Jt(e){var t=void 0!==e?e.dom:document,n=t.body.scrollLeft||t.documentElement.scrollLeft,r=t.body.scrollTop||t.documentElement.scrollTop;return Un(n,r)}function Qt(e,t,n){var r=(void 0!==n?n.dom:document).defaultView;r&&r.scrollTo(e,t)}function Zt(e,t){dt().browser.isSafari()&&y(e.dom.scrollIntoViewIfNeeded)?e.dom.scrollIntoViewIfNeeded(!1):e.dom.scrollIntoView(t)}function en(e,t,n,r){return{x:e,y:t,width:n,height:r,right:e+n,bottom:t+r}}function tn(e){var r=void 0===e?window:e,t=r.document,o=Jt(Et.fromDom(t)),n=void 0===r?window:r;return(dt().browser.isFirefox()?ve.none():ve.from(n.visualViewport)).fold(function(){var e=r.document.documentElement,t=e.clientWidth,n=e.clientHeight;return en(o.left,o.top,t,n)},function(e){return en(Math.max(e.pageLeft,o.left),Math.max(e.pageTop,o.top),e.width,e.height)})}function nn(t){return function(e){return!!e&&e.nodeType===t}}function rn(e){return e&&!Object.getPrototypeOf(e)}function on(e){var n=e.map(function(e){return e.toLowerCase()});return function(e){if(e&&e.nodeName){var t=e.nodeName.toLowerCase();return T(n,t)}return!1}}function an(r,e){var o=e.toLowerCase().split(" ");return function(e){if(Hn(e))for(var t=0;t<o.length;t++){var n=e.ownerDocument.defaultView.getComputedStyle(e,null);if((n?n.getPropertyValue(r):null)===o[t])return!0}return!1}}function un(t){return function(e){return Hn(e)&&e.hasAttribute(t)}}function sn(e){return Hn(e)&&e.hasAttribute("data-mce-bogus")}function cn(e){return Hn(e)&&"TABLE"===e.tagName}function ln(t){return function(e){if(Hn(e)){if(e.contentEditable===t)return!0;if(e.getAttribute("data-mce-contenteditable")===t)return!0}return!1}}function fn(e,t,n){return void 0===n&&(n=o),e.exists(function(e){return n(e,t)})}function dn(e,t,n){return e.isSome()&&t.isSome()?ve.some(n(e.getOrDie(),t.getOrDie())):ve.none()}function mn(e){return void 0!==e.style&&y(e.style.getPropertyValue)}function gn(e,t,n){if(!(X(n)||v(n)||N(n)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",n,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,n+"")}function pn(e,t,n){gn(e.dom,t,n)}function hn(e,t){var n=e.dom;ne(t,function(e,t){gn(n,t,e)})}function vn(e,t){var n=e.dom.getAttribute(t);return null===n?void 0:n}function bn(e,t){return ve.from(vn(e,t))}function yn(e,t){var n=e.dom;return n&&n.hasAttribute&&n.hasAttribute(t)}function Cn(e,t){e.dom.removeAttribute(t)}function xn(e,t){var n=e.dom;ne(t,function(e,t){!function(e,t,n){if(!X(n))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",n,":: Element ",e),new Error("CSS value must be a string: "+n);mn(e)&&e.style.setProperty(t,n)}(n,t,e)})}function wn(e,t){var n=e.dom,r=window.getComputedStyle(n).getPropertyValue(t);return""!==r||Mn(e)?r:Zn(n,t)}function Sn(e,t){var n=e.dom,r=Zn(n,t);return ve.from(r).filter(function(e){return 0<e.length})}function Nn(e){var t={},n=e.dom;if(mn(n))for(var r=0;r<n.style.length;r++){var o=n.style.item(r);t[o]=n.style[o]}return t}function En(e){return M(e,_n)}function kn(e,t){return e.children&&T(e.children,t)}"undefined"!=typeof window||Function("return this;")();var _n=At(1),An=At(3),Rn=At(9),Dn=At(11),Tn=function(e){return A(e.dom.childNodes,Et.fromDom)},On=y(Element.prototype.attachShadow)&&y(Node.prototype.getRootNode),Bn=J(On),Pn=On?function(e){return Et.fromDom(e.dom.getRootNode())}:Dt,Ln=function(e,t){e.dom.appendChild(t.dom)},In=function(e){var t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)},Mn=function(e){var t=An(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;var n=t.ownerDocument,r=Et.fromDom(t),o=Pn(r);return(Ht(o)?ve.some(o):ve.none()).fold(function(){return n.body.contains(t)},a(Mn,Vt))},Fn=function(n,r){return{left:n,top:r,translate:function(e,t){return Fn(n+e,r+t)}}},Un=Fn,zn=function(e){var t,n=e.dom,r=n.ownerDocument.body;return r===n?Un(r.offsetLeft,r.offsetTop):Mn(e)?(t=n.getBoundingClientRect(),Un(t.left,t.top)):Un(0,0)},Hn=nn(1),jn=on(["textarea","input"]),Vn=nn(3),qn=nn(8),$n=nn(9),Wn=nn(11),Kn=on(["br"]),Xn=on(["img"]),Yn=ln("true"),Gn=ln("false"),Jn=on(["td","th"]),Qn=on(["video","audio","object","embed"]),Zn=function(e,t){return mn(e)?e.style.getPropertyValue(t):""},er=dt().browser,tr={},nr={exports:tr};function rr(e){setTimeout(function(){throw e},0)}!function(){var e=this,t=function(){var e,t,n,r={exports:{}};function o(){}function i(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],f(e,this)}function a(n,r){for(;3===n._state;)n=n._value;0!==n._state?(n._handled=!0,i._immediateFn(function(){var e,t=1===n._state?r.onFulfilled:r.onRejected;if(null!==t){try{e=t(n._value)}catch(e){return void s(r.promise,e)}u(r.promise,e)}else(1===n._state?u:s)(r.promise,n._value)})):n._deferreds.push(r)}function u(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var n=e.then;if(e instanceof i)return t._state=3,t._value=e,void c(t);if("function"==typeof n)return void f((r=n,o=e,function(){r.apply(o,arguments)}),t)}t._state=1,t._value=e,c(t)}catch(e){s(t,e)}var r,o}function s(e,t){e._state=2,e._value=t,c(e)}function c(e){2===e._state&&0===e._deferreds.length&&i._immediateFn(function(){e._handled||i._unhandledRejectionFn(e._value)});for(var t=0,n=e._deferreds.length;t<n;t++)a(e,e._deferreds[t]);e._deferreds=null}function l(e,t,n){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.promise=n}function f(e,t){var n=!1;try{e(function(e){n||(n=!0,u(t,e))},function(e){n||(n=!0,s(t,e))})}catch(e){if(n)return;n=!0,s(t,e)}}e=r,t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=setTimeout,i.prototype.catch=function(e){return this.then(null,e)},i.prototype.then=function(e,t){var n=new this.constructor(o);return a(this,new l(e,t,n)),n},i.all=function(e){var u=Array.prototype.slice.call(e);return new i(function(o,i){if(0===u.length)return o([]);for(var a=u.length,e=0;e<u.length;e++)!function t(n,e){try{if(e&&("object"==typeof e||"function"==typeof e)){var r=e.then;if("function"==typeof r)return r.call(e,function(e){t(n,e)},i),0}u[n]=e,0==--a&&o(u)}catch(e){i(e)}}(e,u[e])})},i.resolve=function(t){return t&&"object"==typeof t&&t.constructor===i?t:new i(function(e){e(t)})},i.reject=function(n){return new i(function(e,t){t(n)})},i.race=function(o){return new i(function(e,t){for(var n=0,r=o.length;n<r;n++)o[n].then(e,t)})},i._immediateFn="function"==typeof setImmediate?function(e){setImmediate(e)}:function(e){n(e,0)},i._unhandledRejectionFn=function(e){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)},i._setImmediateFn=function(e){i._immediateFn=e},i._setUnhandledRejectionFn=function(e){i._unhandledRejectionFn=e},e.exports?e.exports=i:t.Promise||(t.Promise=i);var d=r.exports;return{boltExport:("undefined"!=typeof window?window:Function("return this;")()).Promise||d}};"object"==typeof tr&&void 0!==nr?nr.exports=t():(e="undefined"!=typeof globalThis?globalThis:e||self).EphoxContactWrapper=t()}();function or(e){return cr(function(){return new ar(e)})}function ir(a){if(!S(a))throw new Error("cases must be an array");if(0===a.length)throw new Error("there must be at least one case");var u=[],n={};return Y(a,function(e,r){var t=we(e);if(1!==t.length)throw new Error("one and only one name per case");var o=t[0],i=e[o];if(void 0!==n[o])throw new Error("duplicate key detected:"+o);if("cata"===o)throw new Error("cannot have a case named cata (sorry)");if(!S(i))throw new Error("case arguments must be an array");u.push(o),n[o]=function(){for(var n=[],e=0;e<arguments.length;e++)n[e]=arguments[e];var t=n.length;if(t!==i.length)throw new Error("Wrong number of arguments to case "+o+". Expected "+i.length+" ("+i+"), got "+t);return{fold:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];if(e.length!==a.length)throw new Error("Wrong number of arguments to fold. Expected "+a.length+", got "+e.length);return e[r].apply(null,n)},match:function(e){var t=we(e);if(u.length!==t.length)throw new Error("Wrong number of arguments to match. Expected: "+u.join(",")+"\nActual: "+t.join(","));if(!j(u,function(e){return T(t,e)}))throw new Error("Not all branches were specified when using match. Specified: "+t.join(", ")+"\nRequired: "+u.join(", "));return e[o].apply(null,n)},log:function(e){console.log(e,{constructors:u,constructor:o,params:n})}}}}),n}var ar=nr.exports.boltExport,ur=function(e){function r(e){o()?i(e):t.push(e)}var n=ve.none(),t=[],o=function(){return n.isSome()},i=function(t){n.each(function(e){setTimeout(function(){t(e)},0)})};return e(function(e){o()||(n=ve.some(e),Y(t,i),t=[])}),{get:r,map:function(n){return ur(function(t){r(function(e){t(n(e))})})},isReady:o}},sr={nu:ur,pure:function(t){return ur(function(e){e(t)})}},cr=function(n){function e(e){n().then(e,rr)}return{map:function(e){return cr(function(){return n().then(e)})},bind:function(t){return cr(function(){return n().then(function(e){return t(e).toPromise()})})},anonBind:function(e){return cr(function(){return n().then(function(){return e.toPromise()})})},toLazy:function(){return sr.nu(e)},toCached:function(){var e=null;return cr(function(){return e=null===e?n():e})},toPromise:n,get:e}},lr=function(n){return{isValue:w,isError:D,getOr:J(n),getOrThunk:J(n),getOrDie:J(n),or:function(e){return lr(n)},orThunk:function(e){return lr(n)},fold:function(e,t){return t(n)},map:function(e){return lr(e(n))},mapError:function(e){return lr(n)},each:function(e){e(n)},bind:function(e){return e(n)},exists:function(e){return e(n)},forall:function(e){return e(n)},toOptional:function(){return ve.some(n)}}},fr=function(n){return{isValue:D,isError:w,getOr:u,getOrThunk:function(e){return e()},getOrDie:function(){return e=String(n),function(){throw new Error(e)}();var e},or:u,orThunk:function(e){return e()},fold:function(e,t){return e(n)},map:function(e){return fr(n)},mapError:function(e){return fr(e(n))},each:te,bind:function(e){return fr(n)},exists:D,forall:w,toOptional:ve.none}},dr={value:lr,error:fr,fromOption:function(e,t){return e.fold(function(){return fr(t)},lr)}};function mr(e){return e.fold(u,u)}function gr(e,t,n,r,o){return e(n,r)?ve.some(n):y(o)&&o(n)?ve.none():t(n,r,o)}function pr(e,t,n){for(var r=e.dom,o=y(n)?n:D;r.parentNode;){var r=r.parentNode,i=Et.fromDom(r);if(t(i))return ve.some(i);if(o(i))break}return ve.none()}function hr(e,t,n){return gr(function(e,t){return t(e)},pr,e,t,n)}function vr(e,t,n){return pr(e,function(e){return ze(e,t)},n)}function br(e,t){return n=t,He(r=void 0===e?document:e.dom)?ve.none():ve.from(r.querySelector(n)).map(Et.fromDom);var n,r}function yr(e,t,n){return gr(ze,vr,e,t,n)}function Cr(e,t){return"number"!=typeof t&&(t=0),setTimeout(e,t)}function xr(e,t){return"number"!=typeof t&&(t=1),setInterval(e,t)}function wr(n,r){function e(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];clearTimeout(o),o=Cr(function(){n.apply(this,e)},r)}var o;return e.stop=function(){clearTimeout(o)},e}function Sr(m,g){function n(e,t,n){var r,o=Nt._addCacheSuffix(e),i=ue(h,o).getOrThunk(function(){return{id:"mce-u"+p++,passed:[],failed:[],count:0}});function a(e,t){for(var n=e.length;n--;)e[n]();i.status=t,i.passed=[],i.failed=[],r&&(r.onload=null,r.onerror=null,r=null)}function u(){return a(i.passed,2),0}function s(){return a(i.failed,3)}(h[o]=i).count++;var c,l,f,d=function(){var e=d;!function(){for(var e=m.styleSheets,t=e.length;t--;){var n=e[t].ownerNode;if(n&&n.id===r.id)return u(),1}}()&&(Date.now()-l<y?Ar.setTimeout(e):s())};t&&i.passed.push(t),n&&i.failed.push(n),1!==i.status&&(2!==i.status?3!==i.status?(i.status=1,hn(c=Et.fromTag("link",b.dom),{rel:"stylesheet",type:"text/css",id:i.id}),l=Date.now(),g.contentCssCors&&pn(c,"crossOrigin","anonymous"),g.referrerPolicy&&pn(c,"referrerpolicy",g.referrerPolicy),(r=c.dom).onload=d,r.onerror=s,f=c,Ln(jt(v),f),pn(c,"href",o)):s():u())}function o(t){return or(function(e){n(t,i(e,J(dr.value(t))),i(e,J(dr.error(t))))})}function t(e){var n=Nt._addCacheSuffix(e);ue(h,n).each(function(e){var t;0==--e.count&&(delete h[n],t=e.id,br(jt(v),"#"+t).each(In))})}void 0===g&&(g={});var p=0,h={},v=Et.fromDom(m),b=Dt(v),y=g.maxLoadTime||5e3;return{load:n,loadAll:function(e,n,r){var a,t=A(e,o);a=t,or(function(r){var o=[],i=0;0===a.length?r([]):Y(a,function(e,t){var n;e.get((n=t,function(e){o[n]=e,++i>=a.length&&r(o)}))})}).get(function(e){var t=B(e,function(e){return e.isValue()});0<t.fail.length?r(t.fail.map(mr)):n(t.pass.map(mr))})},unload:t,unloadAll:function(e){Y(e,function(e){t(e)})},_setReferrerPolicy:function(e){g.referrerPolicy=e}}}ir([{bothErrors:["error1","error2"]},{firstError:["error1","value2"]},{secondError:["value1","error2"]},{bothValues:["value1","value2"]}]);var Nr,Er,kr=function(e,t){return M(e.dom.childNodes,function(e){return t(Et.fromDom(e))}).map(Et.fromDom)},_r=window.Promise||ar,Ar={requestAnimationFrame:function(e,t){Nr?Nr.then(e):Nr=new _r(function(e){(function(e,t){for(var n=window.requestAnimationFrame,r=["ms","moz","webkit"],o=0;o<r.length&&!n;o++)n=window[r[o]+"RequestAnimationFrame"];(n=n||function(e){window.setTimeout(e,0)})(e,t)})(e,t=t||document.body)}).then(e)},setTimeout:Cr,setInterval:xr,setEditorTimeout:function(e,t,n){return Cr(function(){e.removed||t()},n)},setEditorInterval:function(e,t,n){var r=xr(function(){e.removed?clearInterval(r):t()},n);return r},debounce:wr,throttle:wr,clearInterval:function(e){return clearInterval(e)},clearTimeout:function(e){return clearTimeout(e)}},Rr=(Er=new WeakMap,{forElement:function(e,t){var n=Pn(e).dom;return ve.from(Er.get(n)).getOrThunk(function(){var e=Sr(n,t);return Er.set(n,e),e})}}),Dr=(Tr.prototype.current=function(){return this.node},Tr.prototype.next=function(e){return this.node=this.findSibling(this.node,"firstChild","nextSibling",e),this.node},Tr.prototype.prev=function(e){return this.node=this.findSibling(this.node,"lastChild","previousSibling",e),this.node},Tr.prototype.prev2=function(e){return this.node=this.findPreviousNode(this.node,"lastChild","previousSibling",e),this.node},Tr.prototype.findSibling=function(e,t,n,r){var o,i;if(e){if(!r&&e[t])return e[t];if(e!==this.rootNode){if(o=e[n])return o;for(i=e.parentNode;i&&i!==this.rootNode;i=i.parentNode)if(o=i[n])return o}}},Tr.prototype.findPreviousNode=function(e,t,n,r){var o,i,a;if(e&&(o=e[n],!this.rootNode||o!==this.rootNode)){if(o){if(!r)for(a=o[t];a;a=a[t])if(!a[t])return a;return o}return(i=e.parentNode)&&i!==this.rootNode?i:void 0}},Tr);function Tr(e,t){this.node=e,this.rootNode=t,this.current=this.current.bind(this),this.next=this.next.bind(this),this.prev=this.prev.bind(this),this.prev2=this.prev2.bind(this)}function Or(t){var n;return function(e){return n=n||function(e,t){for(var n={},r=0,o=e.length;r<o;r++){var i=e[r];n[String(i)]=t(i,r)}return n}(t,w),Ee(n,kt(e))}}function Br(e){return _n(e)&&!go(e)}function Pr(e){return _n(e)&&"br"===kt(e)}function Lr(e){return _o(e)&&(e=e.parentNode),ko(e)&&e.hasAttribute("data-mce-caret")}function Ir(e){return _o(e)&&No(e.data)}function Mr(e){return Lr(e)||Ir(e)}function Fr(e){return e.firstChild!==e.lastChild||!Kn(e.firstChild)}function Ur(e){var t=e.container();return!!Vn(t)&&(t.data.charAt(e.offset())===So||e.isAtStart()&&Ir(t.previousSibling))}function zr(e){var t=e.container();return!!Vn(t)&&(t.data.charAt(e.offset()-1)===So||e.isAtEnd()&&Ir(t.nextSibling))}function Hr(e){return e&&e.hasAttribute("data-mce-caret")?(sn(n=(t=e.getElementsByTagName("br"))[t.length-1])&&n.parentNode.removeChild(n),e.removeAttribute("data-mce-caret"),e.removeAttribute("data-mce-bogus"),e.removeAttribute("style"),e.removeAttribute("_moz_abspos"),e):null;var t,n}function jr(e){return Lr(e.startContainer)}function Vr(e){return!Mo(e)&&(Bo(e)?!Po(e.parentNode):Lo(e)||Oo(e)||Io(e)||Fo(e))}function qr(e,t){return Vr(e)&&function(e,t){for(e=e.parentNode;e&&e!==t;e=e.parentNode){if(Fo(e))return!1;if(Do(e))return!0}return!0}(e,t)}function $r(e){return Uo.test(e)}function Wr(e,t){return Vr(e)&&!1===(a=t,Vn(i=e)&&$r(i.data)&&!1===(n=i,r=Et.fromDom(a),vr(Et.fromDom(n),"pre,code",R(je,r)).isSome()))||Hn(o=e)&&"A"===o.nodeName&&!o.hasAttribute("href")&&(o.hasAttribute("name")||o.hasAttribute("id"))||zo(e);var n,r,o,i,a}function Kr(e,t){return function(e,t){var n=0;if(Wr(e,e))return!1;var r=e.firstChild;if(!r)return!0;var o=new Dr(r,e);do{if(t){if(jo(r)){r=o.next(!0);continue}if(Ho(r)){r=o.next();continue}}if(Kn(r))n++,r=o.next();else{if(Wr(r,e))return!1;r=o.next()}}while(r);return n<=1}(e.dom,t=void 0===t||t)}function Xr(e,t){return V(e)&&(Wr(e,t)||Br(Et.fromDom(e)))}function Yr(e){return"span"===e.nodeName.toLowerCase()&&"bookmark"===e.getAttribute("data-mce-type")}function Gr(e,t){var n,r,o,i={};if(e){for(e=e.split(","),t=t||10,n=0;n<e.length;n+=2)r=String.fromCharCode(parseInt(e[n],t)),Go[r]||(o="&"+e[n+1]+";",i[r]=o,i[o]=r);return i}}function Jr(e,t){return e.replace(t?$o:Wo,function(e){return Go[e]||e})}function Qr(e,t){return e.replace(t?$o:Wo,function(e){return 1<e.length?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":Go[e]||"&#"+e.charCodeAt(0)+";"})}function Zr(e,t,n){return n=n||Qo,e.replace(t?$o:Wo,function(e){return Go[e]||n[e]||e})}function eo(e,t){return(e=Nt.trim(e))?e.split(t||" "):[]}function to(e,t){var n=ni(e," ",ni(e.toUpperCase()," "));return oi(n,t)}function no(e){return to("td th li dt dd figcaption caption details summary",e.getTextBlockElements())}function ro(e,n){var r;return e&&(r={},ri(e="string"==typeof e?{"*":e}:e,function(e,t){r[t]=r[t.toUpperCase()]=("map"===n?ni:ii)(e,/[, ]/)})),r}function oo(i){function e(e,t,n){var r=i[e];return r?r=ni(r,/[, ]/,ni(r.toUpperCase(),/[, ]/)):(r=ei[e])||(r=to(t,n),ei[e]=r),r}var t,s,n,r,o,a,u,c,S={},l={},N=[],f={},d={},m=(t=(i=i||{}).schema,c={},ei[t]||(s="id accesskey class dir lang style tabindex title role",n="address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul",r="a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment","html4"!==t&&(s+=" contenteditable contextmenu draggable dropzone hidden spellcheck translate",n+=" article aside details dialog figure main header footer hgroup section nav",r+=" audio canvas command datalist mark meter output picture progress time wbr video ruby bdi keygen"),"html5-strict"!==t&&(s+=" xml:lang",r=[r,u="acronym applet basefont big font strike tt"].join(" "),ri(eo(u),function(e){g(e,"",r)}),n=[n,a="center dir isindex noframes"].join(" "),o=[n,r].join(" "),ri(eo(a),function(e){g(e,"",o)})),o=o||[n,r].join(" "),g("html","manifest","head body"),g("head","","base command link meta noscript script style title"),g("title hr noscript br"),g("base","href target"),g("link","href rel media hreflang type sizes hreflang"),g("meta","name http-equiv content charset"),g("style","media type scoped"),g("script","src async defer type charset"),g("body","onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload",o),g("address dt dd div caption","",o),g("h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn","",r),g("blockquote","cite",o),g("ol","reversed start type","li"),g("ul","","li"),g("li","value",o),g("dl","","dt dd"),g("a","href target rel media hreflang type",r),g("q","cite",r),g("ins del","cite datetime",o),g("img","src sizes srcset alt usemap ismap width height"),g("iframe","src name width height",o),g("embed","src type width height"),g("object","data type typemustmatch name usemap form width height",[o,"param"].join(" ")),g("param","name value"),g("map","name",[o,"area"].join(" ")),g("area","alt coords shape href target rel media hreflang type"),g("table","border","caption colgroup thead tfoot tbody tr"+("html4"===t?" col":"")),g("colgroup","span","col"),g("col","span"),g("tbody thead tfoot","","tr"),g("tr","","td th"),g("td","colspan rowspan headers",o),g("th","colspan rowspan headers scope abbr",o),g("form","accept-charset action autocomplete enctype method name novalidate target",o),g("fieldset","disabled form name",[o,"legend"].join(" ")),g("label","form for",r),g("input","accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"),g("button","disabled form formaction formenctype formmethod formnovalidate formtarget name type value","html4"===t?o:r),g("select","disabled form multiple name required size","option optgroup"),g("optgroup","disabled label","option"),g("option","disabled label selected value"),g("textarea","cols dirname disabled form maxlength name readonly required rows wrap"),g("menu","type label",[o,"li"].join(" ")),g("noscript","",o),"html4"!==t&&(g("wbr"),g("ruby","",[r,"rt rp"].join(" ")),g("figcaption","",o),g("mark rt rp summary bdi","",r),g("canvas","width height",o),g("video","src crossorigin poster preload autoplay mediagroup loop muted controls width height buffered",[o,"track source"].join(" ")),g("audio","src crossorigin preload autoplay mediagroup loop muted controls buffered volume",[o,"track source"].join(" ")),g("picture","","img source"),g("source","src srcset type media sizes"),g("track","kind src srclang label default"),g("datalist","",[r,"option"].join(" ")),g("article section nav aside main header footer","",o),g("hgroup","","h1 h2 h3 h4 h5 h6"),g("figure","",[o,"figcaption"].join(" ")),g("time","datetime",r),g("dialog","open",o),g("command","type label icon disabled checked radiogroup command"),g("output","for form name",r),g("progress","value max",r),g("meter","value min max low high optimum",r),g("details","open",[o,"summary"].join(" ")),g("keygen","autofocus challenge disabled form keytype name")),"html5-strict"!==t&&(p("script","language xml:space"),p("style","xml:space"),p("object","declare classid code codebase codetype archive standby align border hspace vspace"),p("embed","align name hspace vspace"),p("param","valuetype type"),p("a","charset name rev shape coords"),p("br","clear"),p("applet","codebase archive code object alt name width height align hspace vspace"),p("img","name longdesc align border hspace vspace"),p("iframe","longdesc frameborder marginwidth marginheight scrolling align"),p("font basefont","size color face"),p("input","usemap align"),p("select"),p("textarea"),p("h1 h2 h3 h4 h5 h6 div p legend caption","align"),p("ul","type compact"),p("li","type"),p("ol dl menu dir","compact"),p("pre","width xml:space"),p("hr","align noshade size width"),p("isindex","prompt"),p("table","summary width frame rules cellspacing cellpadding align bgcolor"),p("col","width align char charoff valign"),p("colgroup","width align char charoff valign"),p("thead","align char charoff valign"),p("tr","align char charoff valign bgcolor"),p("th","axis align char charoff valign nowrap bgcolor width height"),p("form","accept"),p("td","abbr axis scope align char charoff valign nowrap bgcolor width height"),p("tfoot","align char charoff valign"),p("tbody","align char charoff valign"),p("area","nohref"),p("body","background bgcolor text link vlink alink")),"html4"!==t&&(p("input button select textarea","autofocus"),p("input textarea","placeholder"),p("a","download"),p("link script img","crossorigin"),p("img","loading"),p("iframe","sandbox seamless allowfullscreen loading")),ri(eo("a form meter progress dfn"),function(e){c[e]&&delete c[e].children[e]}),delete c.caption.children.table,delete c.script,ei[t]=c));function g(e,t,n){function r(e,t){for(var n={},r=0,o=e.length;r<o;r++)n[e[r]]=t||{};return n}var o,i;t=t||"","string"==typeof(n=n||[])&&(n=eo(n));for(var a=eo(e),u=a.length;u--;)i={attributes:r(o=eo([s,t].join(" "))),attributesOrder:o,children:r(n,ti)},c[a[u]]=i}function p(e,t){for(var n,r,o,i=eo(e),a=i.length,u=eo(t);a--;)for(n=c[i[a]],r=0,o=u.length;r<o;r++)n.attributes[u[r]]={},n.attributesOrder.push(u[r])}!1===i.verify_html&&(i.valid_elements="*[*]");var h=ro(i.valid_styles),v=ro(i.invalid_styles,"map"),b=ro(i.valid_classes,"map"),y=e("whitespace_elements","pre script noscript style textarea video audio iframe object code"),C=e("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr"),x=e("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source wbr track"),w=e("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls"),E="td th iframe video audio object script code",k=e("non_empty_elements",E+" pre",x),_=e("move_caret_before_on_enter_elements",E+" table",x),A=e("text_block_elements","h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside main nav figure"),R=e("block_elements","hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex option datalist select optgroup figcaption details summary",A),D=e("text_inline_elements","span strong b em i font s strike u var cite dfn code mark q sup sub samp");function T(e){return new RegExp("^"+e.replace(/([?+*])/g,".$1")+"$")}function O(e){var t,n,r,o,i,a,u,s,c,l,f,d,m,g,p,h,v,b,y=/^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)])?$/,C=/^([!\-])?(\w+[\\:]:\w+|[^=:<]+)?(?:([=:<])(.*))?$/,x=/[*?+]/;if(e){var w=eo(e,",");for(S["@"]&&(h=S["@"].attributes,v=S["@"].attributesOrder),t=0,n=w.length;t<n;t++)if(i=y.exec(w[t])){if(g=i[1],c=i[2],p=i[3],s=i[5],a={attributes:d={},attributesOrder:m=[]},"#"===g&&(a.paddEmpty=!0),"-"===g&&(a.removeEmpty=!0),"!"===i[4]&&(a.removeEmptyAttrs=!0),h&&(ne(h,function(e,t){d[t]=e}),m.push.apply(m,v)),s)for(r=0,o=(s=eo(s,"|")).length;r<o;r++)(i=C.exec(s[r]))&&(u={},f=i[1],l=i[2].replace(/[\\:]:/g,":"),g=i[3],b=i[4],"!"===f&&(a.attributesRequired=a.attributesRequired||[],a.attributesRequired.push(l),u.required=!0),"-"!==f?(g&&("="===g&&(a.attributesDefault=a.attributesDefault||[],a.attributesDefault.push({name:l,value:b}),u.defaultValue=b),":"===g&&(a.attributesForced=a.attributesForced||[],a.attributesForced.push({name:l,value:b}),u.forcedValue=b),"<"===g&&(u.validValues=ni(b,"?"))),x.test(l)?(a.attributePatterns=a.attributePatterns||[],u.pattern=T(l),a.attributePatterns.push(u)):(d[l]||m.push(l),d[l]=u)):(delete d[l],m.splice(ai(m,l),1)));h||"@"!==c||(h=d,v=m),p&&(a.outputName=c,S[p]=a),x.test(c)?(a.pattern=T(c),N.push(a)):S[c]=a}}}function B(e){S={},N=[],O(e),ri(m,function(e,t){l[t]=e.children})}function P(e){var a=/^(~)?(.+)$/;e&&(ei.text_block_elements=ei.block_elements=null,ri(eo(e,","),function(e){var t,n=a.exec(e),r="~"===n[1],o=r?"span":"div",i=n[2];l[i]=l[o],f[i]=o,r||(R[i.toUpperCase()]={},R[i]={}),S[i]||(t=S[o],delete(t=oi({},t)).removeEmptyAttrs,delete t.removeEmpty,S[i]=t),ri(l,function(e,t){e[o]&&(l[t]=e=oi({},l[t]),e[i]=e[o])})}))}function L(e){var o=/^([+\-]?)([A-Za-z0-9_\-.\u00b7\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]+)\[([^\]]+)]$/;ei[i.schema]=null,e&&ri(eo(e,","),function(e){var t,n,r=o.exec(e);r&&(n=r[1],t=n?l[r[2]]:l[r[2]]={"#comment":{}},t=l[r[2]],ri(eo(r[3],"|"),function(e){"-"===n?delete t[e]:t[e]={}}))})}function I(e){var t,n=S[e];if(n)return n;for(t=N.length;t--;)if((n=N[t]).pattern.test(e))return n}ri((i.special||"script noscript iframe noframes noembed title style textarea xmp").split(" "),function(e){d[e]=new RegExp("</"+e+"[^>]*>","gi")}),i.valid_elements?B(i.valid_elements):(ri(m,function(e,t){S[t]={attributes:e.attributes,attributesOrder:e.attributesOrder},l[t]=e.children}),"html5"!==i.schema&&ri(eo("strong/b em/i"),function(e){var t=eo(e,"/");S[t[1]].outputName=t[0]}),ri(D,function(e,t){S[t]&&(i.padd_empty_block_inline_children&&(S[t].paddInEmptyBlock=!0),S[t].removeEmpty=!0)}),ri(eo("ol ul blockquote a table tbody"),function(e){S[e]&&(S[e].removeEmpty=!0)}),ri(eo("p h1 h2 h3 h4 h5 h6 th td pre div address caption li"),function(e){S[e].paddEmpty=!0}),ri(eo("span"),function(e){S[e].removeEmptyAttrs=!0})),P(i.custom_elements),L(i.valid_children),O(i.extended_valid_elements),L("+ol[ul|ol],+ul[ul|ol]"),ri({dd:"dl",dt:"dl",li:"ul ol",td:"tr",th:"tr",tr:"tbody thead tfoot",tbody:"table",thead:"table",tfoot:"table",legend:"fieldset",area:"map",param:"video audio object"},function(e,t){S[t]&&(S[t].parentsRequired=eo(e))}),i.invalid_elements&&ri(ii(i.invalid_elements),function(e){S[e]&&delete S[e]}),I("span")||O("span[!data-mce-type|*]");var M=J(h),F=J(v),U=J(b),z=J(w),H=J(R),j=J(A),V=J(D),q=J(x),$=J(C),W=J(k),K=J(_),X=J(y),Y=J(d),G=J(f);return{children:l,elements:S,getValidStyles:M,getValidClasses:U,getBlockElements:H,getInvalidStyles:F,getShortEndedElements:q,getTextBlockElements:j,getTextInlineElements:V,getBoolAttrs:z,getElementRule:I,getSelfClosingElements:$,getNonEmptyElements:W,getMoveCaretBeforeOnEnterElements:K,getWhiteSpaceElements:X,getSpecialElements:Y,isValidChild:function(e,t){var n=l[e.toLowerCase()];return!(!n||!n[t.toLowerCase()])},isValid:function(e,t){var n,r,o=I(e);if(o){if(!t)return!0;if(o.attributes[t])return!0;if(n=o.attributePatterns)for(r=n.length;r--;)if(n[r].pattern.test(e))return!0}return!1},getCustomElements:G,addValidElements:O,setValidElements:B,addCustomElements:P,addValidChildren:L}}function io(e,t,n,r){function o(e){return 1<(e=parseInt(e,10).toString(16)).length?e:"0"+e}return"#"+o(t)+o(n)+o(r)}function ao(b,e){var u,o,y=this,C=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,x=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,w=/\s*([^:]+):\s*([^;]+);?/g,S=/\s+$/,N={},E=xo;b=b||{},e&&(u=e.getValidStyles(),o=e.getInvalidStyles());for(var t=("\\\" \\' \\; \\: ; : "+E).split(" "),k=0;k<t.length;k++)N[t[k]]=E+k,N[E+k]=t[k];return{toHex:function(e){return e.replace(C,io)},parse:function(e){function t(e,t,n){var r=p[e+"-top"+t];if(r){var o=p[e+"-right"+t];if(o){var i=p[e+"-bottom"+t];if(i){var a=p[e+"-left"+t];if(a){var u=[r,o,i,a];for(k=u.length-1;k--&&u[k]===u[k+1];);-1<k&&n||(p[e+t]=-1===k?u[0]:u.join(" "),delete p[e+"-top"+t],delete p[e+"-right"+t],delete p[e+"-bottom"+t],delete p[e+"-left"+t])}}}}}function n(e){var t,n=p[e];if(n){for(t=(n=n.split(" ")).length;t--;)if(n[t]!==n[0])return;return p[e]=n[0],1}}function r(e){return f=!0,N[e]}function u(e,t){return f&&(e=e.replace(/\uFEFF[0-9]/g,function(e){return N[e]})),t?e:e.replace(/\\([\'\";:])/g,"$1")}function o(e){return String.fromCharCode(parseInt(e.slice(1),16))}function i(e){return e.replace(/\\[0-9a-f]+/gi,o)}function a(e,t,n,r,o,i){if(o=o||i)return"'"+(o=u(o)).replace(/\'/g,"\\'")+"'";if(t=u(t||n||r),!b.allow_script_urls){var a=t.replace(/[\s\r\n]+/g,"");if(/(java|vb)script:/i.test(a))return"";if(!b.allow_svg_data_urls&&/^data:image\/svg/i.test(a))return""}return"url('"+(t=h?h.call(v,t,"style"):t).replace(/\'/g,"\\'")+"')"}var s,c,l,f,d,m,g,p={},h=b.url_converter,v=b.url_converter_scope||y;if(e){for(e=(e=e.replace(/[\u0000-\u001F]/g,"")).replace(/\\[\"\';:\uFEFF]/g,r).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(e){return e.replace(/[;:]/g,r)});s=w.exec(e);)w.lastIndex=s.index+s[0].length,c=s[1].replace(S,"").toLowerCase(),l=s[2].replace(S,""),c&&l&&(c=i(c),l=i(l),-1===c.indexOf(E)&&-1===c.indexOf('"')&&(b.allow_script_urls||"behavior"!==c&&!/expression\s*\(|\/\*|\*\//.test(l))&&("font-weight"===c&&"700"===l?l="bold":"color"!==c&&"background-color"!==c||(l=l.toLowerCase()),l=(l=l.replace(C,io)).replace(x,a),p[c]=f?u(l,!0):l));t("border","",!0),t("border","-width"),t("border","-color"),t("border","-style"),t("padding",""),t("margin",""),m="border-style",g="border-color",n(d="border-width")&&n(m)&&n(g)&&(p.border=p[d]+" "+p[m]+" "+p[g],delete p[d],delete p[m],delete p[g]),"medium none"===p.border&&delete p.border,"none"===p["border-image"]&&delete p["border-image"]}return p},serialize:function(i,r){function e(e){var t,n=u[e];if(n)for(var r=0,o=n.length;r<o;r++)e=n[r],(t=i[e])&&(a+=(0<a.length?" ":"")+e+": "+t+";")}var a="";return r&&u?(e("*"),e(r)):ne(i,function(e,t){var n;!e||o&&((n=o["*"])&&n[t]||(n=o[r])&&n[t])||(a+=(0<a.length?" ":"")+t+": "+e+";")}),a}}}function uo(e){return e instanceof Event||y(e.initEvent)}function so(e,t,n,r){var o,i,a=function(e){var t,n=null!=r?r:{};for(t in e)Ee(ui,t)||(n[t]=e[t]);return V(n.composedPath)&&(n.composedPath=function(){return e.composedPath()}),n}(t);return a.type=e,K(a.target)&&(a.target=null!==(o=a.srcElement)&&void 0!==o?o:n),(K((i=t).preventDefault)||uo(i))&&(a.preventDefault=function(){a.defaultPrevented=!0,a.isDefaultPrevented=w,y(t.preventDefault)?t.preventDefault():uo(t)&&(t.returnValue=!1)},a.stopPropagation=function(){a.cancelBubble=!0,a.isPropagationStopped=w,y(t.stopPropagation)?t.stopPropagation():uo(t)&&(t.cancelBubble=!0)},a.stopImmediatePropagation=function(){a.isImmediatePropagationStopped=w,a.stopPropagation()},a.isDefaultPrevented!==w&&a.isDefaultPrevented!==D&&(a.isDefaultPrevented=!0===a.defaultPrevented?w:D,a.isPropagationStopped=!0===a.cancelBubble?w:D,a.isImmediatePropagationStopped=D)),a}function co(e,t,n,r){e.addEventListener?e.addEventListener(t,n,r||!1):e.attachEvent&&e.attachEvent("on"+t,n)}function lo(e,t,n,r){e.removeEventListener?e.removeEventListener(t,n,r||!1):e.detachEvent&&e.detachEvent("on"+t,n)}function fo(e,t){var n,r,o,i,a=so(e.type,e,document,t);return V(i=e)&&si.test(i.type)&&b(e.pageX)&&!b(e.clientX)&&(r=(n=a.target.ownerDocument||document).documentElement,o=n.body,a.pageX=e.clientX+(r&&r.scrollLeft||o&&o.scrollLeft||0)-(r&&r.clientLeft||o&&o.clientLeft||0),a.pageY=e.clientY+(r&&r.scrollTop||o&&o.scrollTop||0)-(r&&r.clientTop||o&&o.clientTop||0)),b(a.metaKey)&&(a.metaKey=!1),a}var mo=Or(["h1","h2","h3","h4","h5","h6"]),go=Or(["article","aside","details","div","dt","figcaption","footer","form","fieldset","header","hgroup","html","main","nav","section","summary","body","p","dl","multicol","dd","figure","address","center","blockquote","h1","h2","h3","h4","h5","h6","listing","xmp","pre","plaintext","menu","dir","ul","ol","li","hr","table","tbody","thead","tfoot","th","tr","td","caption"]),po=Or(["h1","h2","h3","h4","h5","h6","p","div","address","pre","form","blockquote","center","dir","fieldset","header","footer","article","section","hgroup","aside","nav","figure"]),ho=Or(["ul","ol","dl"]),vo=Or(["li","dd","dt"]),bo=Or(["thead","tbody","tfoot"]),yo=Or(["td","th"]),Co=Or(["pre","script","textarea","style"]),xo="\ufeff",wo="\xa0",So=xo,No=function(e){return e===xo},Eo=function(e){return e.replace(/\uFEFF/g,"")},ko=Hn,_o=Vn,Ao=function(e){return _o(e)&&e.data[0]===So},Ro=function(e){return _o(e)&&e.data[e.data.length-1]===So},Do=Yn,To=Gn,Oo=Kn,Bo=Vn,Po=on(["script","style","textarea"]),Lo=on(["img","input","textarea","hr","iframe","video","audio","object","embed"]),Io=on(["table"]),Mo=Mr,Fo=function(e){return!1===(Hn(t=e)&&"true"===t.getAttribute("unselectable"))&&To(e);var t},Uo=/^[ \t\r\n]*$/,zo=un("data-mce-bookmark"),Ho=un("data-mce-bogus"),jo=function(e){return Hn(e)&&"all"===e.getAttribute("data-mce-bogus")},Vo=function(e,t,n){var r=n||t;if(Hn(t)&&Yr(t))return t;for(var o,i,a,u,s,c,l,f,d,m,g,p=t.childNodes,h=p.length-1;0<=h;h--)Vo(e,p[h],r);return!Hn(t)||1===(o=t.childNodes).length&&Yr(o[0])&&t.parentNode.insertBefore(o[0],t),Wn(a=t)||$n(a)||Wr(t,r)||Hn(i=t)&&0<i.childNodes.length||(s=r,Vn(u=t)&&0<u.data.length&&(f=new Dr(c=u,l=s).prev(!1),d=new Dr(c,l).next(!1),m=b(f)||Xr(f,l),g=b(d)||Xr(d,l),m&&g))||e.remove(t),t},qo=Nt.makeMap,$o=/[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,Wo=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,Ko=/[<>&\"\']/g,Xo=/&#([a-z0-9]+);?|&([a-z0-9]+);/gi,Yo={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"},Go={'"':""","'":"'","<":"<",">":">","&":"&","`":"`"},Jo={"<":"<",">":">","&":"&",""":'"',"'":"'"},Qo=Gr("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32),Zo={encodeRaw:Jr,encodeAllRaw:function(e){return(""+e).replace(Ko,function(e){return Go[e]||e})},encodeNumeric:Qr,encodeNamed:Zr,getEncodeFunc:function(e,t){var n=Gr(t)||Qo,r=qo(e.replace(/\+/g,","));return r.named&&r.numeric?function(e,t){return e.replace(t?$o:Wo,function(e){return void 0!==Go[e]?Go[e]:void 0!==n[e]?n[e]:1<e.length?"&#"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+";":"&#"+e.charCodeAt(0)+";"})}:r.named?t?function(e,t){return Zr(e,t,n)}:Zr:r.numeric?Qr:Jr},decode:function(e){return e.replace(Xo,function(e,t){return t?65535<(t="x"===t.charAt(0).toLowerCase()?parseInt(t.substr(1),16):parseInt(t,10))?(t-=65536,String.fromCharCode(55296+(t>>10),56320+(1023&t))):Yo[t]||String.fromCharCode(t):Jo[e]||Qo[e]||(n=e,(r=Et.fromTag("div").dom).innerHTML=n,r.textContent||r.innerText||n);var n,r})}},ei={},ti={},ni=Nt.makeMap,ri=Nt.each,oi=Nt.extend,ii=Nt.explode,ai=Nt.inArray,ui={keyLocation:!0,layerX:!0,layerY:!0,returnValue:!0,webkitMovementX:!0,webkitMovementY:!0,keyIdentifier:!0,mozPressure:!0},si=/^(?:mouse|contextmenu)|click/,ci=(li.prototype.bind=function(e,t,n,r){function o(e){f.executeHandlers(fo(e||d.event),i)}var i,a,u,s,c,l,f=this,d=window;if(e&&3!==e.nodeType&&8!==e.nodeType){e[f.expando]?i=e[f.expando]:(i=f.count++,e[f.expando]=i,f.events[i]={}),r=r||e;for(var m=t.split(" "),g=m.length;g--;)c=o,s=l=!1,"DOMContentLoaded"===(u=m[g])&&(u="ready"),f.domLoaded&&"ready"===u&&"complete"===e.readyState?n.call(r,fo({type:u})):(f.hasMouseEnterLeave||(s=f.mouseEnterLeave[u])&&(c=function(e){var t=e.currentTarget,n=e.relatedTarget;if(n&&t.contains)n=t.contains(n);else for(;n&&n!==t;)n=n.parentNode;n||((e=fo(e||d.event)).type="mouseout"===e.type?"mouseleave":"mouseenter",e.target=t,f.executeHandlers(e,i))}),f.hasFocusIn||"focusin"!==u&&"focusout"!==u||(l=!0,s="focusin"===u?"focus":"blur",c=function(e){(e=fo(e||d.event)).type="focus"===e.type?"focusin":"focusout",f.executeHandlers(e,i)}),(a=f.events[i][u])?"ready"===u&&f.domLoaded?n(fo({type:u})):a.push({func:n,scope:r}):(f.events[i][u]=a=[{func:n,scope:r}],a.fakeName=s,a.capture=l,a.nativeHandler=c,"ready"===u?function(e,t,n){var r,o=e.document,i={type:"ready"};n.domLoaded?t(i):(r=function(){lo(e,"DOMContentLoaded",r),lo(e,"load",r),n.domLoaded||(n.domLoaded=!0,t(i)),e=null},"complete"===o.readyState||"interactive"===o.readyState&&o.body?r():co(e,"DOMContentLoaded",r),n.domLoaded||co(e,"load",r))}(e,c,f):co(e,s||u,c,l)));return e=a=null,n}},li.prototype.unbind=function(n,e,t){var r,o,i;if(!n||3===n.nodeType||8===n.nodeType)return this;var a=n[this.expando];if(a){if(i=this.events[a],e){for(var u,s,c,l,f=e.split(" "),d=f.length;d--;)if(l=i[o=f[d]]){if(t)for(r=l.length;r--;)l[r].func===t&&(u=l.nativeHandler,s=l.fakeName,c=l.capture,(l=l.slice(0,r).concat(l.slice(r+1))).nativeHandler=u,l.fakeName=s,l.capture=c,i[o]=l);t&&0!==l.length||(delete i[o],lo(n,l.fakeName||o,l.nativeHandler,l.capture))}}else ne(i,function(e,t){lo(n,e.fakeName||t,e.nativeHandler,e.capture)}),i={};for(o in i)if(Ee(i,o))return this;delete this.events[a];try{delete n[this.expando]}catch(e){n[this.expando]=null}}return this},li.prototype.fire=function(e,t,n){var r;if(!e||3===e.nodeType||8===e.nodeType)return this;for(var o=fo({type:t,target:e},n);(r=e[this.expando])&&this.executeHandlers(o,r),(e=e.parentNode||e.ownerDocument||e.defaultView||e.parentWindow)&&!o.isPropagationStopped(););return this},li.prototype.clean=function(e){var t,n;if(!e||3===e.nodeType||8===e.nodeType)return this;if(e[this.expando]&&this.unbind(e),(e=e.getElementsByTagName?e:e.document)&&e.getElementsByTagName)for(this.unbind(e),t=(n=e.getElementsByTagName("*")).length;t--;)(e=n[t])[this.expando]&&this.unbind(e);return this},li.prototype.destroy=function(){this.events={}},li.prototype.cancel=function(e){return e&&(e.preventDefault(),e.stopImmediatePropagation()),!1},li.prototype.executeHandlers=function(e,t){var n=this.events[t],r=n&&n[e.type];if(r)for(var o=0,i=r.length;o<i;o++){var a=r[o];if(a&&!1===a.func.call(a.scope,e)&&e.preventDefault(),e.isImmediatePropagationStopped())return}},li.Event=new li,li);function li(){this.domLoaded=!1,this.events={},this.count=1,this.expando="mce-data-"+(+new Date).toString(32),this.hasMouseEnterLeave="onmouseenter"in document.documentElement,this.hasFocusIn="onfocusin"in document.documentElement,this.count=1}function fi(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(65536+r):String.fromCharCode(r>>10|55296,1023&r|56320)}var di,mi,gi,pi,hi,vi,bi,yi,Ci,xi,wi,Si,Ni,Ei,ki,_i,Ai,Ri="sizzle"+-new Date,Di=window.document,Ti=0,Oi=0,Bi=la(),Pi=la(),Li=la(),Ii=function(e,t){return e===t&&(xi=!0),0},Mi="undefined",Fi={}.hasOwnProperty,Ui=[],zi=Ui.pop,Hi=Ui.push,ji=Ui.push,Vi=Ui.slice,qi=Ui.indexOf||function(e){for(var t=0,n=this.length;t<n;t++)if(this[t]===e)return t;return-1},$i="[\\x20\\t\\r\\n\\f]",Wi="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",Ki="\\["+$i+"*("+Wi+")(?:"+$i+"*([*^$|!~]?=)"+$i+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+Wi+"))|)"+$i+"*\\]",Xi=":("+Wi+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+Ki+")*)|.*)\\)|)",Yi=new RegExp("^"+$i+"+|((?:^|[^\\\\])(?:\\\\.)*)"+$i+"+$","g"),Gi=new RegExp("^"+$i+"*,"+$i+"*"),Ji=new RegExp("^"+$i+"*([>+~]|"+$i+")"+$i+"*"),Qi=new RegExp("="+$i+"*([^\\]'\"]*?)"+$i+"*\\]","g"),Zi=new RegExp(Xi),ea=new RegExp("^"+Wi+"$"),ta={ID:new RegExp("^#("+Wi+")"),CLASS:new RegExp("^\\.("+Wi+")"),TAG:new RegExp("^("+Wi+"|[*])"),ATTR:new RegExp("^"+Ki),PSEUDO:new RegExp("^"+Xi),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+$i+"*(even|odd|(([+-]|)(\\d*)n|)"+$i+"*(?:([+-]|)"+$i+"*(\\d+)|))"+$i+"*\\)|)","i"),bool:new RegExp("^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$","i"),needsContext:new RegExp("^"+$i+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+$i+"*((?:-\\d)?\\d*)"+$i+"*\\)|)(?=[^-]|$)","i")},na=/^(?:input|select|textarea|button)$/i,ra=/^h\d$/i,oa=/^[^{]+\{\s*\[native \w/,ia=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ua=/'|\\/g,sa=new RegExp("\\\\([\\da-f]{1,6}"+$i+"?|("+$i+")|.)","ig");try{ji.apply(Ui=Vi.call(Di.childNodes),Di.childNodes),Ui[Di.childNodes.length].nodeType}catch(e){ji={apply:Ui.length?function(e,t){Hi.apply(e,Vi.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}var ca=function(e,t,n,r){var o,i,a,u,s,c,l,f,d,m;if((t?t.ownerDocument||t:Di)!==Si&&wi(t),n=n||[],!e||"string"!=typeof e)return n;if(1!==(u=(t=t||Si).nodeType)&&9!==u)return[];if(Ei&&!r){if(o=ia.exec(e))if(a=o[1]){if(9===u){if(!(i=t.getElementById(a))||!i.parentNode)return n;if(i.id===a)return n.push(i),n}else if(t.ownerDocument&&(i=t.ownerDocument.getElementById(a))&&Ai(t,i)&&i.id===a)return n.push(i),n}else{if(o[2])return ji.apply(n,t.getElementsByTagName(e)),n;if((a=o[3])&&di.getElementsByClassName)return ji.apply(n,t.getElementsByClassName(a)),n}if(di.qsa&&(!ki||!ki.test(e))){if(f=l=Ri,d=t,m=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){for(c=hi(e),(l=t.getAttribute("id"))?f=l.replace(ua,"\\$&"):t.setAttribute("id",f),f="[id='"+f+"'] ",s=c.length;s--;)c[s]=f+ha(c[s]);d=aa.test(e)&&ga(t.parentNode)||t,m=c.join(",")}if(m)try{return ji.apply(n,d.querySelectorAll(m)),n}catch(e){}finally{l||t.removeAttribute("id")}}}return bi(e.replace(Yi,"$1"),t,n,r)};function la(){var n=[];function r(e,t){return n.push(e+" ")>mi.cacheLength&&delete r[n.shift()],r[e+" "]=t}return r}function fa(e){return e[Ri]=!0,e}function da(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||1<<31)-(~e.sourceIndex||1<<31);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function ma(a){return fa(function(i){return i=+i,fa(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ga(e){return e&&typeof e.getElementsByTagName!=Mi&&e}function pa(){}function ha(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function va(a,e,t){var u=e.dir,s=t&&"parentNode"===u,c=Oi++;return e.first?function(e,t,n){for(;e=e[u];)if(1===e.nodeType||s)return a(e,t,n)}:function(e,t,n){var r,o,i=[Ti,c];if(n){for(;e=e[u];)if((1===e.nodeType||s)&&a(e,t,n))return!0}else for(;e=e[u];)if(1===e.nodeType||s){if((r=(o=e[Ri]||(e[Ri]={}))[u])&&r[0]===Ti&&r[1]===c)return i[2]=r[2];if((o[u]=i)[2]=a(e,t,n))return!0}}}function ba(o){return 1<o.length?function(e,t,n){for(var r=o.length;r--;)if(!o[r](e,t,n))return!1;return!0}:o[0]}function ya(e,t,n,r,o){for(var i,a=[],u=0,s=e.length,c=null!=t;u<s;u++)(i=e[u])&&(n&&!n(i,r,o)||(a.push(i),c&&t.push(u)));return a}function Ca(e){return void 0!==e}function xa(e){return"string"==typeof e}function wa(e,t){var n,r=(t=t||Ra).createElement("div"),o=t.createDocumentFragment();for(r.innerHTML=e;n=r.firstChild;)o.appendChild(n);return o}function Sa(e,t){return e&&t&&-1!==(" "+e.className+" ").indexOf(" "+t+" ")}function Na(e,t,n){var r,o;return t=Ya(t)[0],e.each(function(){n&&r===this.parentNode||(r=this.parentNode,o=t.cloneNode(!1),this.parentNode.insertBefore(o,this)),o.appendChild(this)}),e}function Ea(e,t){return new Ya.fn.init(e,t)}function ka(e){return null==e?"":(""+e).replace(ja,"")}function _a(e,t){var n,r,o,i;if(e)if(void 0===(n=e.length)){for(r in e)if(e.hasOwnProperty(r)&&(i=e[r],!1===t.call(i,r,i)))break}else for(o=0;o<n&&(i=e[o],!1!==t.call(i,o,i));o++);return e}function Aa(e,n){var r=[];return _a(e,function(e,t){n(t,e)&&r.push(t)}),r}di=ca.support={},pi=ca.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},wi=ca.setDocument=function(e){var t,s=e?e.ownerDocument||e:Di,n=s.defaultView;return s!==Si&&9===s.nodeType&&s.documentElement?(Ni=(Si=s).documentElement,Ei=!pi(s),n&&n!==function(e){try{return e.top}catch(e){}return null}(n)&&(n.addEventListener?n.addEventListener("unload",function(){wi()},!1):n.attachEvent&&n.attachEvent("onunload",function(){wi()})),di.attributes=!0,di.getElementsByTagName=!0,di.getElementsByClassName=oa.test(s.getElementsByClassName),di.getById=!0,mi.find.ID=function(e,t){if(typeof t.getElementById!=Mi&&Ei){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},mi.filter.ID=function(e){var t=e.replace(sa,fi);return function(e){return e.getAttribute("id")===t}},mi.find.TAG=di.getElementsByTagName?function(e,t){if(typeof t.getElementsByTagName!=Mi)return t.getElementsByTagName(e)}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if("*"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},mi.find.CLASS=di.getElementsByClassName&&function(e,t){if(Ei)return t.getElementsByClassName(e)},_i=[],ki=[],di.disconnectedMatch=!0,ki=ki.length&&new RegExp(ki.join("|")),_i=_i.length&&new RegExp(_i.join("|")),t=oa.test(Ni.compareDocumentPosition),Ai=t||oa.test(Ni.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},Ii=t?function(e,t){return e===t?(xi=!0,0):(n=!e.compareDocumentPosition-!t.compareDocumentPosition)||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!di.sortDetached&&t.compareDocumentPosition(e)===n?e===s||e.ownerDocument===Di&&Ai(Di,e)?-1:t===s||t.ownerDocument===Di&&Ai(Di,t)?1:Ci?qi.call(Ci,e)-qi.call(Ci,t):0:4&n?-1:1);var n}:function(e,t){if(e===t)return xi=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],u=[t];if(!o||!i)return e===s?-1:t===s?1:o?-1:i?1:Ci?qi.call(Ci,e)-qi.call(Ci,t):0;if(o===i)return da(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;a[r]===u[r];)r++;return r?da(a[r],u[r]):a[r]===Di?-1:u[r]===Di?1:0},s):Si},ca.matches=function(e,t){return ca(e,null,null,t)},ca.matchesSelector=function(e,t){if((e.ownerDocument||e)!==Si&&wi(e),t=t.replace(Qi,"='$1']"),di.matchesSelector&&Ei&&(!_i||!_i.test(t))&&(!ki||!ki.test(t)))try{var n=(void 0).call(e,t);if(n||di.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){}return 0<ca(t,Si,null,[e]).length},ca.contains=function(e,t){return(e.ownerDocument||e)!==Si&&wi(e),Ai(e,t)},ca.attr=function(e,t){(e.ownerDocument||e)!==Si&&wi(e);var n=mi.attrHandle[t.toLowerCase()],r=n&&Fi.call(mi.attrHandle,t.toLowerCase())?n(e,t,!Ei):void 0;return void 0!==r?r:di.attributes||!Ei?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},ca.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},ca.uniqueSort=function(e){var t,n=[],r=0,o=0;if(xi=!di.detectDuplicates,Ci=!di.sortStable&&e.slice(0),e.sort(Ii),xi){for(;t=e[o++];)t===e[o]&&(r=n.push(o));for(;r--;)e.splice(n[r],1)}return Ci=null,e},gi=ca.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=gi(e)}else if(3===o||4===o)return e.nodeValue}else for(;t=e[r++];)n+=gi(t);return n},(mi=ca.selectors={cacheLength:50,createPseudo:fa,match:ta,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(sa,fi),e[3]=(e[3]||e[4]||e[5]||"").replace(sa,fi),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ca.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ca.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return ta.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&Zi.test(n)&&(t=hi(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(sa,fi).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=Bi[e+" "];return t||(t=new RegExp("(^|"+$i+")"+e+"("+$i+"|$)"))&&Bi(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!=Mi&&e.getAttribute("class")||"")})},ATTR:function(n,r,o){return function(e){var t=ca.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===o:"!="===r?t!==o:"^="===r?o&&0===t.indexOf(o):"*="===r?o&&-1<t.indexOf(o):"$="===r?o&&t.slice(-o.length)===o:"~="===r?-1<(" "+t+" ").indexOf(o):"|="===r&&(t===o||t.slice(0,o.length+1)===o+"-"))}},CHILD:function(m,e,t,g,p){var h="nth"!==m.slice(0,3),v="last"!==m.slice(-4),b="of-type"===e;return 1===g&&0===p?function(e){return!!e.parentNode}:function(e,t,n){var r,o,i,a,u,s,c=h!=v?"nextSibling":"previousSibling",l=e.parentNode,f=b&&e.nodeName.toLowerCase(),d=!n&&!b;if(l){if(h){for(;c;){for(i=e;i=i[c];)if(b?i.nodeName.toLowerCase()===f:1===i.nodeType)return!1;s=c="only"===m&&!s&&"nextSibling"}return!0}if(s=[v?l.firstChild:l.lastChild],v&&d){for(u=(r=(o=l[Ri]||(l[Ri]={}))[m]||[])[0]===Ti&&r[1],a=r[0]===Ti&&r[2],i=u&&l.childNodes[u];i=++u&&i&&i[c]||(a=u=0)||s.pop();)if(1===i.nodeType&&++a&&i===e){o[m]=[Ti,u,a];break}}else if(d&&(r=(e[Ri]||(e[Ri]={}))[m])&&r[0]===Ti)a=r[1];else for(;(i=++u&&i&&i[c]||(a=u=0)||s.pop())&&((b?i.nodeName.toLowerCase()!==f:1!==i.nodeType)||!++a||(d&&((i[Ri]||(i[Ri]={}))[m]=[Ti,a]),i!==e)););return(a-=p)===g||a%g==0&&0<=a/g}}},PSEUDO:function(e,i){var t,a=mi.pseudos[e]||mi.setFilters[e.toLowerCase()]||ca.error("unsupported pseudo: "+e);return a[Ri]?a(i):1<a.length?(t=[e,e,"",i],mi.setFilters.hasOwnProperty(e.toLowerCase())?fa(function(e,t){for(var n,r=a(e,i),o=r.length;o--;)e[n=qi.call(e,r[o])]=!(t[n]=r[o])}):function(e){return a(e,0,t)}):a}},pseudos:{not:fa(function(e){var r=[],o=[],u=vi(e.replace(Yi,"$1"));return u[Ri]?fa(function(e,t,n,r){for(var o,i=u(e,null,r,[]),a=e.length;a--;)(o=i[a])&&(e[a]=!(t[a]=o))}):function(e,t,n){return r[0]=e,u(r,null,n,o),r[0]=null,!o.pop()}}),has:fa(function(t){return function(e){return 0<ca(t,e).length}}),contains:fa(function(t){return t=t.replace(sa,fi),function(e){return-1<(e.textContent||e.innerText||gi(e)).indexOf(t)}}),lang:fa(function(n){return ea.test(n||"")||ca.error("unsupported lang: "+n),n=n.replace(sa,fi).toLowerCase(),function(e){var t;do{if(t=Ei?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=window.location&&window.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===Ni},focus:function(e){return e===Si.activeElement&&(!Si.hasFocus||Si.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return!1===e.disabled},disabled:function(e){return!0===e.disabled},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!mi.pseudos.empty(e)},header:function(e){return ra.test(e.nodeName)},input:function(e){return na.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ma(function(){return[0]}),last:ma(function(e,t){return[t-1]}),eq:ma(function(e,t,n){return[n<0?n+t:n]}),even:ma(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ma(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ma(function(e,t,n){for(var r=n<0?n+t:n;0<=--r;)e.push(r);return e}),gt:ma(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=mi.pseudos.eq,Y(["radio","checkbox","file","password","image"],function(e){var t;mi.pseudos[e]=(t=e,function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t})}),Y(["submit","reset"],function(e){var n;mi.pseudos[e]=(n=e,function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n})}),pa.prototype=mi.filters=mi.pseudos,mi.setFilters=new pa,hi=ca.tokenize=function(e,t){var n,r,o,i,a,u,s,c=Pi[e+" "];if(c)return t?0:c.slice(0);for(a=e,u=[],s=mi.preFilter;a;){for(i in n&&!(r=Gi.exec(a))||(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=Ji.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(Yi," ")}),a=a.slice(n.length)),mi.filter)mi.filter.hasOwnProperty(i)&&(!(r=ta[i].exec(a))||s[i]&&!(r=s[i](r))||(n=r.shift(),o.push({value:n,type:i,matches:r}),a=a.slice(n.length)));if(!n)break}return t?a.length:a?ca.error(e):Pi(e,u).slice(0)},vi=ca.compile=function(e,t){var n,h,v,b,y,r=[],o=[],i=Li[e+" "];if(!i){for(n=(t=t||hi(e)).length;n--;)((i=function e(t){for(var o,n,r,i=t.length,a=mi.relative[t[0].type],u=a||mi.relative[" "],s=a?1:0,c=va(function(e){return e===o},u,!0),l=va(function(e){return-1<qi.call(o,e)},u,!0),f=[function(e,t,n){var r=!a&&(n||t!==yi)||((o=t).nodeType?c:l)(e,t,n);return o=null,r}];s<i;s++)if(n=mi.relative[t[s].type])f=[va(ba(f),n)];else{if((n=mi.filter[t[s].type].apply(null,t[s].matches))[Ri]){for(r=++s;r<i&&!mi.relative[t[r].type];r++);return function e(m,g,p,h,v,t){return h&&!h[Ri]&&(h=e(h)),v&&!v[Ri]&&(v=e(v,t)),fa(function(e,t,n,r){var o,i,a,u=[],s=[],c=t.length,l=e||function(e,t,n){for(var r=0,o=t.length;r<o;r++)ca(e,t[r],n);return n}(g||"*",n.nodeType?[n]:n,[]),f=!m||!e&&g?l:ya(l,u,m,n,r),d=p?v||(e?m:c||h)?[]:t:f;if(p&&p(f,d,n,r),h)for(o=ya(d,s),h(o,[],n,r),i=o.length;i--;)(a=o[i])&&(d[s[i]]=!(f[s[i]]=a));if(e){if(v||m){if(v){for(o=[],i=d.length;i--;)(a=d[i])&&o.push(f[i]=a);v(null,d=[],o,r)}for(i=d.length;i--;)(a=d[i])&&-1<(o=v?qi.call(e,a):u[i])&&(e[o]=!(t[o]=a))}}else d=ya(d===t?d.splice(c,d.length):d),v?v(null,t,d,r):ji.apply(t,d)})}(1<s&&ba(f),1<s&&ha(t.slice(0,s-1).concat({value:" "===t[s-2].type?"*":""})).replace(Yi,"$1"),n,s<r&&e(t.slice(s,r)),r<i&&e(t=t.slice(r)),r<i&&ha(t))}f.push(n)}return ba(f)}(t[n]))[Ri]?r:o).push(i);(i=Li(e,(h=o,b=0<(v=r).length,y=0<h.length,b?fa(a):a))).selector=e}function a(e,t,n,r,o){var i,a,u,s=0,c="0",l=e&&[],f=[],d=yi,m=e||y&&mi.find.TAG("*",o),g=Ti+=null==d?1:Math.random()||.1,p=m.length;for(o&&(yi=t!==Si&&t);c!==p&&null!=(i=m[c]);c++){if(y&&i){for(a=0;u=h[a++];)if(u(i,t,n)){r.push(i);break}o&&(Ti=g)}b&&((i=!u&&i)&&s--,e&&l.push(i))}if(s+=c,b&&c!==s){for(a=0;u=v[a++];)u(l,f,t,n);if(e){if(0<s)for(;c--;)l[c]||f[c]||(f[c]=zi.call(r));f=ya(f)}ji.apply(r,f),o&&!e&&0<f.length&&1<s+v.length&&ca.uniqueSort(r)}return o&&(Ti=g,yi=d),l}return i},bi=ca.select=function(e,t,n,r){var o,i,a,u,s,c="function"==typeof e&&e,l=!r&&hi(e=c.selector||e);if(n=n||[],1===l.length){if(2<(i=l[0]=l[0].slice(0)).length&&"ID"===(a=i[0]).type&&di.getById&&9===t.nodeType&&Ei&&mi.relative[i[1].type]){if(!(t=(mi.find.ID(a.matches[0].replace(sa,fi),t)||[])[0]))return n;c&&(t=t.parentNode),e=e.slice(i.shift().value.length)}for(o=ta.needsContext.test(e)?0:i.length;o--&&(a=i[o],!mi.relative[u=a.type]);)if((s=mi.find[u])&&(r=s(a.matches[0].replace(sa,fi),aa.test(i[0].type)&&ga(t.parentNode)||t))){if(i.splice(o,1),!(e=r.length&&ha(i)))return ji.apply(n,r),n;break}}return(c||vi(e,l))(r,t,!Ei,n,aa.test(e)&&ga(t.parentNode)||t),n},di.sortStable=Ri.split("").sort(Ii).join("")===Ri,di.detectDuplicates=!!xi,wi(),di.sortDetached=!0;var Ra=document,Da=Array.prototype.push,Ta=Array.prototype.slice,Oa=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,Ba=ci.Event,Pa=Nt.makeMap("children,contents,next,prev"),La=function(e,t,n,r){var o;if(xa(t))t=wa(t,Va(e[0]));else if(t.length&&!t.nodeType){if(t=Ya.makeArray(t),r)for(o=t.length-1;0<=o;o--)La(e,t[o],n,r);else for(o=0;o<t.length;o++)La(e,t[o],n,r);return e}if(t.nodeType)for(o=e.length;o--;)n.call(e[o],t);return e},Ia=Nt.makeMap("fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom"," "),Ma=Nt.makeMap("checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected"," "),Fa={for:"htmlFor",class:"className",readonly:"readOnly"},Ua={float:"cssFloat"},za={},Ha={},ja=/^\s*|\s*$/g,Va=function(e){return e?9===e.nodeType?e:e.ownerDocument:Ra};function qa(e,t,n){var r=[],o=e[t];for("string"!=typeof n&&n instanceof Ya&&(n=n[0]);o&&9!==o.nodeType;){if(void 0!==n){if(o===n)break;if("string"==typeof n&&Ya(o).is(n))break}1===o.nodeType&&r.push(o),o=o[t]}return r}function $a(e,t,n,r){var o=[];for(r instanceof Ya&&(r=r[0]);e;e=e[t])if(!n||e.nodeType===n){if(void 0!==r){if(e===r)break;if("string"==typeof r&&Ya(e).is(r))break}o.push(e)}return o}function Wa(e,t,n){for(e=e[t];e;e=e[t])if(e.nodeType===n)return e;return null}function Ka(e,t){var n=t.attr("style"),r=e.serialize(e.parse(n),t[0].nodeName)||null;t.attr("data-mce-style",r)}function Xa(e,t){var n,r,o=0;if(e)for(n=e.nodeType,e=e.previousSibling;e;e=e.previousSibling)r=e.nodeType,(!t||3!==r||r!==n&&e.nodeValue.length)&&(o++,n=r);return o}Ea.fn=Ea.prototype={constructor:Ea,selector:"",context:null,length:0,init:function(e,t){var n,r,o=this;if(!e)return o;if(e.nodeType)return o.context=o[0]=e,o.length=1,o;if(t&&t.nodeType)o.context=t;else{if(t)return Ya(e).attr(t);o.context=t=document}if(xa(e)){if(!(n="<"===(o.selector=e).charAt(0)&&">"===e.charAt(e.length-1)&&3<=e.length?[null,e,null]:Oa.exec(e)))return Ya(t).find(e);if(n[1])for(r=wa(e,Va(t)).firstChild;r;)Da.call(o,r),r=r.nextSibling;else{if(!(r=Va(t).getElementById(n[2])))return o;if(r.id!==n[2])return o.find(e);o.length=1,o[0]=r}}else this.add(e,!1);return o},toArray:function(){return Nt.toArray(this)},add:function(e,t){var n,r;if(xa(e))return this.add(Ya(e));if(!1!==t)for(n=Ya.unique(this.toArray().concat(Ya.makeArray(e))),this.length=n.length,r=0;r<n.length;r++)this[r]=n[r];else Da.apply(this,Ya.makeArray(e));return this},attr:function(t,n){var e,r=this;if("object"==typeof t)_a(t,function(e,t){r.attr(e,t)});else{if(!Ca(n)){if(r[0]&&1===r[0].nodeType){if((e=za[t])&&e.get)return e.get(r[0],t);if(Ma[t])return r.prop(t)?t:void 0;null===(n=r[0].getAttribute(t,2))&&(n=void 0)}return n}this.each(function(){var e;1===this.nodeType&&((e=za[t])&&e.set?e.set(this,n):null===n?this.removeAttribute(t,2):this.setAttribute(t,n,2))})}return r},removeAttr:function(e){return this.attr(e,null)},prop:function(e,t){var n=this;if("object"==typeof(e=Fa[e]||e))_a(e,function(e,t){n.prop(e,t)});else{if(!Ca(t))return n[0]&&n[0].nodeType&&e in n[0]?n[0][e]:t;this.each(function(){1===this.nodeType&&(this[e]=t)})}return n},css:function(t,n){function e(e){return e.replace(/-(\D)/g,function(e,t){return t.toUpperCase()})}function r(e){return e.replace(/[A-Z]/g,function(e){return"-"+e})}var o,i,a=this;if("object"==typeof t)_a(t,function(e,t){a.css(e,t)});else if(Ca(n))t=e(t),"number"!=typeof n||Ia[t]||(n=n.toString()+"px"),a.each(function(){var e=this.style;if((i=Ha[t])&&i.set)i.set(this,n);else{try{this.style[Ua[t]||t]=n}catch(e){}null!==n&&""!==n||(e.removeProperty?e.removeProperty(r(t)):e.removeAttribute(t))}});else{if(o=a[0],(i=Ha[t])&&i.get)return i.get(o);if(!o.ownerDocument.defaultView)return o.currentStyle?o.currentStyle[e(t)]:"";try{return o.ownerDocument.defaultView.getComputedStyle(o,null).getPropertyValue(r(t))}catch(e){return}}return a},remove:function(){for(var e,t=this.length;t--;)e=this[t],Ba.clean(e),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var e,t=this.length;t--;)for(e=this[t];e.firstChild;)e.removeChild(e.firstChild);return this},html:function(t){var n;if(Ca(t)){n=this.length;try{for(;n--;)this[n].innerHTML=t}catch(e){Ya(this[n]).empty().append(t)}return this}return this[0]?this[0].innerHTML:""},text:function(e){var t;if(Ca(e)){for(t=this.length;t--;)"innerText"in this[t]?this[t].innerText=e:this[0].textContent=e;return this}return this[0]?this[0].innerText||this[0].textContent:""},append:function(){return La(this,arguments,function(e){(1===this.nodeType||this.host&&1===this.host.nodeType)&&this.appendChild(e)})},prepend:function(){return La(this,arguments,function(e){(1===this.nodeType||this.host&&1===this.host.nodeType)&&this.insertBefore(e,this.firstChild)},!0)},before:function(){return this[0]&&this[0].parentNode?La(this,arguments,function(e){this.parentNode.insertBefore(e,this)}):this},after:function(){return this[0]&&this[0].parentNode?La(this,arguments,function(e){this.parentNode.insertBefore(e,this.nextSibling)},!0):this},appendTo:function(e){return Ya(e).append(this),this},prependTo:function(e){return Ya(e).prepend(this),this},replaceWith:function(e){return this.before(e).remove()},wrap:function(e){return Na(this,e)},wrapAll:function(e){return Na(this,e,!0)},wrapInner:function(e){return this.each(function(){Ya(this).contents().wrapAll(e)}),this},unwrap:function(){return this.parent().each(function(){Ya(this).replaceWith(this.childNodes)})},clone:function(){var e=[];return this.each(function(){e.push(this.cloneNode(!0))}),Ya(e)},addClass:function(e){return this.toggleClass(e,!0)},removeClass:function(e){return this.toggleClass(e,!1)},toggleClass:function(o,i){var e=this;return"string"!=typeof o||(-1!==o.indexOf(" ")?_a(o.split(" "),function(){e.toggleClass(this,i)}):e.each(function(e,t){var n,r=Sa(t,o);r!==i&&(n=t.className,r?t.className=ka((" "+n+" ").replace(" "+o+" "," ")):t.className+=n?" "+o:o)})),e},hasClass:function(e){return Sa(this[0],e)},each:function(e){return _a(this,e)},on:function(e,t){return this.each(function(){Ba.bind(this,e,t)})},off:function(e,t){return this.each(function(){Ba.unbind(this,e,t)})},trigger:function(e){return this.each(function(){"object"==typeof e?Ba.fire(this,e.type,e):Ba.fire(this,e)})},show:function(){return this.css("display","")},hide:function(){return this.css("display","none")},slice:function(){return Ya(Ta.apply(this,arguments))},eq:function(e){return-1===e?this.slice(e):this.slice(e,+e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},find:function(e){for(var t=[],n=0,r=this.length;n<r;n++)Ya.find(e,this[n],t);return Ya(t)},filter:function(n){return Ya("function"==typeof n?Aa(this.toArray(),function(e,t){return n(t,e)}):Ya.filter(n,this.toArray()))},closest:function(n){var r=[];return n instanceof Ya&&(n=n[0]),this.each(function(e,t){for(;t;){if("string"==typeof n&&Ya(t).is(n)){r.push(t);break}if(t===n){r.push(t);break}t=t.parentNode}}),Ya(r)},offset:function(e){var t,n,r,o,i=0,a=0;return e?this.css(e):((t=this[0])&&(r=(n=t.ownerDocument).documentElement,t.getBoundingClientRect&&(i=(o=t.getBoundingClientRect()).left+(r.scrollLeft||n.body.scrollLeft)-r.clientLeft,a=o.top+(r.scrollTop||n.body.scrollTop)-r.clientTop)),{left:i,top:a})},push:Da,sort:Array.prototype.sort,splice:Array.prototype.splice},Nt.extend(Ea,{extend:Nt.extend,makeArray:function(e){return e&&e===e.window||e.nodeType?[e]:Nt.toArray(e)},inArray:function(e,t){var n;if(t.indexOf)return t.indexOf(e);for(n=t.length;n--;)if(t[n]===e)return n;return-1},isArray:Nt.isArray,each:_a,trim:ka,grep:Aa,find:ca,expr:ca.selectors,unique:ca.uniqueSort,text:ca.getText,contains:ca.contains,filter:function(e,t,n){var r=t.length;for(n&&(e=":not("+e+")");r--;)1!==t[r].nodeType&&t.splice(r,1);return 1===t.length?Ya.find.matchesSelector(t[0],e)?[t[0]]:[]:Ya.find.matches(e,t)}}),_a({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return qa(e,"parentNode")},next:function(e){return Wa(e,"nextSibling",1)},prev:function(e){return Wa(e,"previousSibling",1)},children:function(e){return $a(e.firstChild,"nextSibling",1)},contents:function(e){return Nt.toArray(("iframe"===e.nodeName?e.contentDocument||e.contentWindow.document:e).childNodes)}},function(r,o){Ea.fn[r]=function(t){var n=[];this.each(function(){var e=o.call(n,this,t,n);e&&(Ya.isArray(e)?n.push.apply(n,e):n.push(e))}),1<this.length&&(Pa[r]||(n=Ya.unique(n)),0===r.indexOf("parents")&&(n=n.reverse()));var e=Ya(n);return t?e.filter(t):e}}),_a({parentsUntil:function(e,t){return qa(e,"parentNode",t)},nextUntil:function(e,t){return $a(e,"nextSibling",1,t).slice(1)},prevUntil:function(e,t){return $a(e,"previousSibling",1,t).slice(1)}},function(o,i){Ea.fn[o]=function(t,e){var n=[];this.each(function(){var e=i.call(n,this,t,n);e&&(Ya.isArray(e)?n.push.apply(n,e):n.push(e))}),1<this.length&&(n=Ya.unique(n),0!==o.indexOf("parents")&&"prevUntil"!==o||(n=n.reverse()));var r=Ya(n);return e?r.filter(e):r}}),Ea.fn.is=function(e){return!!e&&0<this.filter(e).length},Ea.fn.init.prototype=Ea.fn,Ea.overrideDefaults=function(n){var r,o=function(e,t){return r=r||n(),0===arguments.length&&(e=r.element),t=t||r.context,new o.fn.init(e,t)};return Ya.extend(o,this),o},Ea.attrHooks=za,Ea.cssHooks=Ha;var Ya=Ea,Ga=Nt.each,Ja=Nt.grep,Qa=xt.ie,Za=/^([a-z0-9],?)+$/i,eu=function(a,u){function s(e){return e&&a&&X(e)?a.getElementById(e):e}function c(e){return H("string"==typeof e?s(e):e)}function r(e,t,n){var r,o,i=c(e);return void 0===(o=i.length?(r=W[t])&&r.get?r.get(i,t):i.attr(t):o)?n||"":o}function o(e){var t=s(e);return t?t.attributes:[]}function i(e,t,n){""===n&&(n=null);var r,o=c(e),i=o.attr(t);o.length&&((r=W[t])&&r.set?r.set(o,n,t):o.attr(t,n),i!==n&&u.onSetAttrib&&u.onSetAttrib({attrElm:o,attrName:t,attrValue:n}))}function l(){return u.root_element||a.body}function f(e,t){return function(e,t,n){var r,o=0,i=0,a=e.ownerDocument;if(n=n||e,t){if(n===e&&t.getBoundingClientRect&&"static"===wn(Et.fromDom(e),"position")){var u=t.getBoundingClientRect();return{x:o=u.left+(a.documentElement.scrollLeft||e.scrollLeft)-a.documentElement.clientLeft,y:i=u.top+(a.documentElement.scrollTop||e.scrollTop)-a.documentElement.clientTop}}for(var s=t;s&&s!==n&&s.nodeType&&!kn(s,n);){var c=s;o+=c.offsetLeft||0,i+=c.offsetTop||0,s=c.offsetParent}for(s=t.parentNode;s&&s!==n&&s.nodeType&&!kn(s,n);)o-=s.scrollLeft||0,i-=s.scrollTop||0,s=s.parentNode;i+=(r=Et.fromDom(t),er.isFirefox()&&"table"===kt(r)?En(Tn(r)).filter(function(e){return"caption"===kt(e)}).bind(function(o){return En(It(o)).map(function(e){var t=e.dom.offsetTop,n=o.dom.offsetTop,r=o.dom.offsetHeight;return t<=n?-r:0})}).getOr(0):0)}return{x:o,y:i}}(a.body,s(e),t)}function d(e,t,n){var r=c(e);return n?r.css(t):("float"===(t=t.replace(/-(\D)/g,function(e,t){return t.toUpperCase()}))&&(t=xt.browser.isIE()?"styleFloat":"cssFloat"),r[0]&&r[0].style?r[0].style[t]:void 0)}function m(e){var t=d(e=s(e),"width"),n=d(e,"height");return-1===t.indexOf("px")&&(t=0),-1===n.indexOf("px")&&(n=0),{w:parseInt(t,10)||e.offsetWidth||e.clientWidth,h:parseInt(n,10)||e.offsetHeight||e.clientHeight}}function g(e,t){if(!e)return!1;if(!Array.isArray(e)){if("*"===t)return 1===e.nodeType;if(Za.test(t)){for(var n=t.toLowerCase().split(/,/),r=e.nodeName.toLowerCase(),o=n.length-1;0<=o;o--)if(n[o]===r)return!0;return!1}if(e.nodeType&&1!==e.nodeType)return!1}var i=Array.isArray(e)?e:[e];return 0<ca(t,i[0].ownerDocument||i[0],null,i).length}function p(e,t,n,r){var o,i=[],a=s(e);for(r=void 0===r,n=n||("BODY"!==l().nodeName?l().parentNode:null),Nt.is(t,"string")&&(t="*"===(o=t)?function(e){return 1===e.nodeType}:function(e){return g(e,o)});a&&!(a===n||K(a.nodeType)||$n(a)||Wn(a));){if(!t||"function"==typeof t&&t(a)){if(!r)return[a];i.push(a)}a=a.parentNode}return r?i:null}function n(e,t,n){var r=t;if(e)for("string"==typeof t&&(r=function(e){return g(e,t)}),e=e[n];e;e=e[n])if("function"==typeof r&&r(e))return e;return null}function h(e,n,r){var o,t="string"==typeof e?s(e):e;return!!t&&(Nt.isArray(t)&&(t.length||0===t.length)?(o=[],Ga(t,function(e,t){e&&o.push(n.call(r,"string"==typeof e?s(e):e,t))}),o):n.call(r||this,t))}function v(e,t){c(e).each(function(e,n){Ga(t,function(e,t){i(n,t,e)})})}function b(e,n){var t=c(e);Qa?t.each(function(e,t){if(!1!==t.canHaveHTML){for(;t.firstChild;)t.removeChild(t.firstChild);try{t.innerHTML="<br>"+n,t.removeChild(t.firstChild)}catch(e){Ya("<div></div>").html("<br>"+n).contents().slice(1).appendTo(t)}return n}}):t.html(n)}function y(e,n,r,o,i){return h(e,function(e){var t="string"==typeof n?a.createElement(n):n;return v(t,r),o&&("string"!=typeof o&&o.nodeType?t.appendChild(o):"string"==typeof o&&b(t,o)),i?t:e.appendChild(t)})}function C(e,t,n){return y(a.createElement(e),e,t,n,!0)}function x(e,t){var n=c(e);return(t?n.each(function(){for(var e;e=this.firstChild;)3===e.nodeType&&0===e.data.length?this.removeChild(e):this.parentNode.insertBefore(e,this)}):n).remove(),1<n.length?n.toArray():n[0]}function w(e,t,n){c(e).toggleClass(t,n).each(function(){""===this.className&&Ya(this).attr("class",null)})}function S(t,e,n){return h(e,function(e){return Nt.is(e,"array")&&(t=t.cloneNode(!0)),n&&Ga(Ja(e.childNodes),function(e){t.appendChild(e)}),e.parentNode.replaceChild(t,e)})}function N(e){if(Hn(e)){var t="a"===e.nodeName.toLowerCase()&&!r(e,"href")&&r(e,"id");return r(e,"name")||r(e,"data-mce-bookmark")||t?1:void 0}}function E(){return a.createRange()}function k(e){if(e&&Hn(e)){var t=e.getAttribute("data-mce-contenteditable");return t&&"inherit"!==t?t:"inherit"!==e.contentEditable?e.contentEditable:null}return null}void 0===u&&(u={});var _,A,R,D,e,t,T={},O=window,B={},P=0,L=Rr.forElement(Et.fromDom(a),{contentCssCors:u.contentCssCors,referrerPolicy:u.referrerPolicy}),I=[],M=u.schema||oo({}),F=ao({url_converter:u.url_converter,url_converter_scope:u.url_converter_scope},u.schema),U=u.ownEvents?new ci:ci.Event,z=M.getBlockElements(),H=Ya.overrideDefaults(function(){return{context:a,element:$.getRoot()}}),j=Zo.encodeAllRaw,V=function(e,t,n,r){if(Nt.isArray(e)){for(var o=e.length,i=[];o--;)i[o]=V(e[o],t,n,r);return i}return!u.collect||e!==a&&e!==O||I.push([e,t,n,r]),U.bind(e,t,n,r||$)},q=function(e,t,n){if(Nt.isArray(e)){for(var r=e.length,o=[];r--;)o[r]=q(e[r],t,n);return o}if(0<I.length&&(e===a||e===O))for(r=I.length;r--;){var i=I[r];e!==i[0]||t&&t!==i[1]||n&&n!==i[2]||U.unbind(i[0],i[1],i[2])}return U.unbind(e,t,n)},$={doc:a,settings:u,win:O,files:B,stdMode:!0,boxModel:!0,styleSheetLoader:L,boundEvents:I,styles:F,schema:M,events:U,isBlock:function(e){if("string"==typeof e)return!!z[e];if(e){var t=e.nodeType;if(t)return!(1!==t||!z[e.nodeName])}return!1},$:H,$$:c,root:null,clone:function(t,e){if(!Qa||1!==t.nodeType||e)return t.cloneNode(e);var n=a.createElement(t.nodeName);return Ga(o(t),function(e){i(n,e.nodeName,r(t,e.nodeName))}),n},getRoot:l,getViewPort:function(e){var t=tn(e);return{x:t.x,y:t.y,w:t.width,h:t.height}},getRect:function(e){var t=f(e=s(e)),n=m(e);return{x:t.x,y:t.y,w:n.w,h:n.h}},getSize:m,getParent:function(e,t,n){var r=p(e,t,n,!1);return r&&0<r.length?r[0]:null},getParents:p,get:s,getNext:function(e,t){return n(e,t,"nextSibling")},getPrev:function(e,t){return n(e,t,"previousSibling")},select:function(e,t){return ca(e,s(t)||u.root_element||a,[])},is:g,add:y,create:C,createHTML:function(e,t,n){var r,o="";for(r in o+="<"+e,t)se(t,r)&&(o+=" "+r+'="'+j(t[r])+'"');return void 0!==n?o+">"+n+"</"+e+">":o+" />"},createFragment:function(e){var t,n=a.createElement("div"),r=a.createDocumentFragment();for(r.appendChild(n),e&&(n.innerHTML=e);t=n.firstChild;)r.appendChild(t);return r.removeChild(n),r},remove:x,setStyle:function(e,t,n){var r=X(t)?c(e).css(t,n):c(e).css(t);u.update_styles&&Ka(F,r)},getStyle:d,setStyles:function(e,t){var n=c(e).css(t);u.update_styles&&Ka(F,n)},removeAllAttribs:function(e){return h(e,function(e){for(var t=e.attributes,n=t.length-1;0<=n;n--)e.removeAttributeNode(t.item(n))})},setAttrib:i,setAttribs:v,getAttrib:r,getPos:f,parseStyle:function(e){return F.parse(e)},serializeStyle:function(e,t){return F.serialize(e,t)},addStyle:function(e){var t,n;if($!==eu.DOM&&a===document){if(T[e])return;T[e]=!0}(n=a.getElementById("mceDefaultStyles"))||((n=a.createElement("style")).id="mceDefaultStyles",n.type="text/css",(t=a.getElementsByTagName("head")[0]).firstChild?t.insertBefore(n,t.firstChild):t.appendChild(n)),n.styleSheet?n.styleSheet.cssText+=e:n.appendChild(a.createTextNode(e))},loadCSS:function(e){Y((e=e||"").split(","),function(e){B[e]=!0,L.load(e,te)})},addClass:function(e,t){c(e).addClass(t)},removeClass:function(e,t){w(e,t,!1)},hasClass:function(e,t){return c(e).hasClass(t)},toggleClass:w,show:function(e){c(e).show()},hide:function(e){c(e).hide()},isHidden:function(e){return"none"===c(e).css("display")},uniqueId:function(e){return(e||"mce_")+P++},setHTML:b,getOuterHTML:function(e){var t="string"==typeof e?s(e):e;return Hn(t)?t.outerHTML:Ya("<div></div>").append(Ya(t).clone()).html()},setOuterHTML:function(e,t){c(e).each(function(){try{if("outerHTML"in this)return void(this.outerHTML=t)}catch(e){}x(Ya(this).html(t),!0)})},decode:Zo.decode,encode:j,insertAfter:function(e,t){var r=s(t);return h(e,function(e){var t=r.parentNode,n=r.nextSibling;return n?t.insertBefore(e,n):t.appendChild(e),e})},replace:S,rename:function(t,e){var n;return t.nodeName!==e.toUpperCase()&&(n=C(e),Ga(o(t),function(e){i(n,e.nodeName,r(t,e.nodeName))}),S(n,t,!0)),n||t},findCommonAncestor:function(e,t){for(var n,r=e;r;){for(n=t;n&&r!==n;)n=n.parentNode;if(r===n)break;r=r.parentNode}return!r&&e.ownerDocument?e.ownerDocument.documentElement:r},toHex:function(e){return F.toHex(Nt.trim(e))},run:h,getAttribs:o,isEmpty:function(e,t){var n,r,o=0;if(N(e))return!1;if(e=e.firstChild){var i=new Dr(e,e.parentNode),a=M?M.getWhiteSpaceElements():{};t=t||(M?M.getNonEmptyElements():null);do{if(n=e.nodeType,Hn(e)){var u=e.getAttribute("data-mce-bogus");if(u){e=i.next("all"===u);continue}if(r=e.nodeName.toLowerCase(),t&&t[r]){if("br"!==r)return!1;o++,e=i.next();continue}if(N(e))return!1}if(8===n)return!1;if(3===n&&!$r(e.nodeValue))return!1;if(3===n&&e.parentNode&&a[e.parentNode.nodeName]&&$r(e.nodeValue))return!1;e=i.next()}while(e)}return o<=1},createRng:E,nodeIndex:Xa,split:function(e,t,n){var r,o,i,a=E();if(e&&t)return a.setStart(e.parentNode,Xa(e)),a.setEnd(t.parentNode,Xa(t)),r=a.extractContents(),(a=E()).setStart(t.parentNode,Xa(t)+1),a.setEnd(e.parentNode,Xa(e)+1),o=a.extractContents(),(i=e.parentNode).insertBefore(Vo($,r),e),n?i.insertBefore(n,e):i.insertBefore(t,e),i.insertBefore(Vo($,o),e),x(e),n||t},bind:V,unbind:q,fire:function(e,t,n){return U.fire(e,t,n)},getContentEditable:k,getContentEditableParent:function(e){for(var t=l(),n=null;e&&e!==t&&null===(n=k(e));e=e.parentNode);return n},destroy:function(){if(0<I.length)for(var e=I.length;e--;){var t=I[e];U.unbind(t[0],t[1],t[2])}ne(B,function(e,t){L.unload(t),delete B[t]}),ca.setDocument&&ca.setDocument()},isChildOf:function(e,t){if(Qa){for(;e;){if(t===e)return!0;e=e.parentNode}return!1}return e===t||t.contains(e)},dumpRng:function(e){return"startContainer: "+e.startContainer.nodeName+", startOffset: "+e.startOffset+", endContainer: "+e.endContainer.nodeName+", endOffset: "+e.endOffset}},W=(_=F,R=J($),e={set:function(e,t,n){A.url_converter&&null!==t&&(t=A.url_converter.call(A.url_converter_scope||R(),t,n,e[0])),e.attr("data-mce-"+n,t).attr(n,t)},get:function(e,t){return e.attr("data-mce-"+t)||e.attr(t)}},t={style:{set:function(e,t){null===t||"object"!=typeof t?(D&&e.attr("data-mce-style",t),null!==t&&"string"==typeof t?(e.removeAttr("style"),e.css(_.parse(t))):e.attr("style",t)):e.css(t)},get:function(e){var t=e.attr("data-mce-style")||e.attr("style");return _.serialize(_.parse(t),e[0].nodeName)}}},(D=(A=u).keep_values)&&(t.href=t.src=e),t);return $};eu.DOM=eu(document),eu.nodeIndex=Xa;var tu=eu.DOM,nu=Nt.each,ru=Nt.grep,ou=(iu.prototype._setReferrerPolicy=function(e){this.settings.referrerPolicy=e},iu.prototype.loadScript=function(e,t,n){function r(){o.remove(i),a&&(a.onerror=a.onload=a=null)}var o=tu,i=o.uniqueId(),a=document.createElement("script");a.id=i,a.type="text/javascript",a.src=Nt._addCacheSuffix(e),this.settings.referrerPolicy&&o.setAttrib(a,"referrerpolicy",this.settings.referrerPolicy),a.onload=function(){r(),t()},a.onerror=function(){r(),y(n)?n():"undefined"!=typeof console&&console.log&&console.log("Failed to load script: "+e)},(document.getElementsByTagName("head")[0]||document.body).appendChild(a)},iu.prototype.isDone=function(e){return 2===this.states[e]},iu.prototype.markDone=function(e){this.states[e]=2},iu.prototype.add=function(e,t,n,r){var o=this.states[e];this.queue.push(e),void 0===o&&(this.states[e]=0),t&&(this.scriptLoadedCallbacks[e]||(this.scriptLoadedCallbacks[e]=[]),this.scriptLoadedCallbacks[e].push({success:t,failure:r,scope:n||this}))},iu.prototype.load=function(e,t,n,r){return this.add(e,t,n,r)},iu.prototype.remove=function(e){delete this.states[e],delete this.scriptLoadedCallbacks[e]},iu.prototype.loadQueue=function(e,t,n){this.loadScripts(this.queue,e,t,n)},iu.prototype.loadScripts=function(n,e,t,r){function o(t,e){nu(i.scriptLoadedCallbacks[e],function(e){y(e[t])&&e[t].call(e.scope)}),i.scriptLoadedCallbacks[e]=void 0}var i=this,a=[];i.queueLoadedCallbacks.push({success:e,failure:r,scope:t||this});var u=function(){var e,t=ru(n);n.length=0,nu(t,function(e){2!==i.states[e]?3!==i.states[e]?1!==i.states[e]&&(i.states[e]=1,i.loading++,i.loadScript(e,function(){i.states[e]=2,i.loading--,o("success",e),u()},function(){i.states[e]=3,i.loading--,a.push(e),o("failure",e),u()})):o("failure",e):o("success",e)}),i.loading||(e=i.queueLoadedCallbacks.slice(0),i.queueLoadedCallbacks.length=0,nu(e,function(e){0===a.length?y(e.success)&&e.success.call(e.scope):y(e.failure)&&e.failure.call(e.scope,a)}))};u()},iu.ScriptLoader=new iu,iu);function iu(e){void 0===e&&(e={}),this.states={},this.queue=[],this.scriptLoadedCallbacks={},this.queueLoadedCallbacks=[],this.loading=0,this.settings=e}function au(e){var t=e;return{get:function(){return t},set:function(e){t=e}}}function uu(){return ue(su,cu.get())}var su={},cu=au("en"),lu={getData:function(){return re(su,function(e){return _e({},e)})},setCode:function(e){e&&cu.set(e)},getCode:function(){return cu.get()},add:function(e,t){var n=su[e];n||(su[e]=n={}),ne(t,function(e,t){n[t.toLowerCase()]=e})},translate:function(e){function n(e){return y(e)?Object.prototype.toString.call(e):u(e)?"":""+e}function t(e){var t=n(e);return ue(a,t.toLowerCase()).map(n).getOr(t)}function r(e){return e.replace(/{context:\w+}$/,"")}var o,i,a=uu().getOr({}),u=function(e){return""===e||null==e};if(u(e))return"";if(h(o=e)&&Ee(o,"raw"))return n(e.raw);if(S(i=e)&&1<i.length){var s=e.slice(1);return r(t(e[0]).replace(/\{([0-9]+)\}/g,function(e,t){return Ee(s,t)?n(s[t]):e}))}return r(t(e))},isRtl:function(){return uu().bind(function(e){return ue(e,"_dir")}).exists(function(e){return"rtl"===e})},hasCode:function(e){return Ee(su,e)}},fu=function(){function u(t,n){Y(U(r,function(e){return e.name===t&&e.state===n}),function(e){return e.callback()})}function s(e){var t;return(f[e]?f[e].dependencies:t)||[]}function c(e,t){return"object"==typeof t?t:"string"==typeof e?{prefix:"",resource:t,suffix:""}:{prefix:e.prefix,resource:t,suffix:e.suffix}}function e(e,t,n){void 0===n&&(n="added"),Ee(f,e)&&"added"===n||Ee(l,e)&&"loaded"===n?t():r.push({name:e,state:n,callback:t})}var o=[],l={},f={},r=[],d=function(r,o,i,a,e){var t,n;l[r]||(0!==(t="string"==typeof o?o:o.prefix+o.resource+o.suffix).indexOf("/")&&-1===t.indexOf("://")&&(t=fu.baseURL+"/"+t),l[r]=t.substring(0,t.lastIndexOf("/")),n=function(){var n,e,t;u(r,"loaded"),n=o,e=i,t=a,Y(s(r),function(e){var t=c(n,e);d(t.resource,t,void 0,void 0)}),e&&(t?e.call(t):e.call(ou))},f[r]?n():ou.ScriptLoader.add(t,n,a,e))};return{items:o,urls:l,lookup:f,_listeners:r,get:function(e){if(f[e])return f[e].instance},dependencies:s,requireLangPack:function(t,n){!1!==fu.languageLoad&&e(t,function(){var e=lu.getCode();!e||n&&-1===(","+(n||"")+",").indexOf(","+e+",")||ou.ScriptLoader.add(l[t]+"/langs/"+e+".js")},"loaded")},add:function(e,t,n){var r=t;return o.push(r),f[e]={instance:r,dependencies:n},u(e,"added"),r},remove:function(e){delete l[e],delete f[e]},createUrl:c,addComponents:function(e,t){var n=l[e];Y(t,function(e){ou.ScriptLoader.add(n+"/"+e)})},load:d,waitFor:e}};function du(){var e,t,n=(e=te,t=au(ve.none()),{clear:function(){r(),t.set(ve.none())},isSet:function(){return t.get().isSome()},get:function(){return t.get()},set:function(e){r(),t.set(ve.some(e))}});function r(){return t.get().each(e)}return _e(_e({},n),{on:function(e){return n.get().each(e)}})}function mu(n,r){var o=null;return{cancel:function(){l(o)||(clearTimeout(o),o=null)},throttle:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];l(o)&&(o=setTimeout(function(){o=null,n.apply(null,e)},r))}}}function gu(n,r){function o(){l(i)||(clearTimeout(i),i=null)}var i=null;return{cancel:o,throttle:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];o(),i=setTimeout(function(){i=null,n.apply(null,e)},r)}}}function pu(e,t){var n=vn(e,t);return void 0===n||""===n?[]:n.split(" ")}function hu(e){return void 0!==e.dom.classList}function vu(e,t){var n,r,o;hu(e)?e.dom.classList.add(t):(r=t,o=pu(n=e,"class").concat([r]),pn(n,"class",o.join(" ")))}function bu(e,t){return hu(e)&&e.dom.classList.contains(t)}function yu(e,t){return He(n=void 0===e?document:e.dom)?[]:A(n.querySelectorAll(t),Et.fromDom);var n}function Cu(r,e){function t(e,t){return yn(e,t)?ve.some(vn(e,t)):ve.none()}var n=r.selection.getRng(),o=Et.fromDom(n.startContainer),i=Et.fromDom(r.getBody()),a=e.fold(function(){return"."+$u()},function(e){return"["+Wu()+'="'+e+'"]'});return yr(Mt(o,n.startOffset).getOr(o),a,function(e){return je(e,i)}).bind(function(e){return t(e,""+Ku()).bind(function(n){return t(e,""+Wu()).map(function(e){var t=Xu(r,n);return{uid:n,name:e,elements:t}})})})}function xu(t){function o(){return{listeners:[],previous:du()}}function c(e,t){n(e,function(e){return t(e),e})}function n(e,t){var n=i.get(),r=t(ue(n,e).getOrThunk(o));n[e]=r,i.set(n)}var i=au({}),e=gu(function(){var e=i.get();Y(W(we(e)),function(e){n(e,function(u){var s=u.previous.get();return Cu(t,ve.some(e)).fold(function(){var t;s.isSome()&&(c(t=e,function(e){Y(e.listeners,function(e){return e(!1,t)})}),u.previous.clear())},function(e){var t,n,r,o=e.uid,i=e.name,a=e.elements;fn(s,o)||(n=o,r=a,c(t=i,function(e){Y(e.listeners,function(e){return e(!0,t,{uid:n,nodes:A(r,function(e){return e.dom})})})}),u.previous.set(o))}),{previous:u.previous,listeners:u.listeners}})})},30);return t.on("remove",function(){e.cancel()}),t.on("NodeChange",function(){e.throttle()}),{addListener:function(e,t){n(e,function(e){return{previous:e.previous,listeners:e.listeners.concat([t])}})}}}function wu(e){var t=(new Date).getTime();return e+"_"+Math.floor(1e9*Math.random())+ ++Yu+String(t)}function Su(e,t){var n,r,o=Rt(e).dom,i=Et.fromDom(o.createDocumentFragment());Kt(i,(n=t,(r=(o||document).createElement("div")).innerHTML=n,Tn(Et.fromDom(r)))),Xt(e),Ln(e,i)}function Nu(e,t){return Et.fromDom(e.dom.cloneNode(t))}function Eu(e){return Nu(e,!1)}function ku(e){return Nu(e,!0)}function _u(e,t,n){function r(e){for(var t;(t=o[e]())&&!Vn(t)&&!n(t););return ve.from(t).filter(Vn)}void 0===n&&(n=D);var o=new Dr(e,t);return{current:function(){return ve.from(o.current()).filter(Vn)},next:function(){return r("next")},prev:function(){return r("prev")},prev2:function(){return r("prev2")}}}function Au(t,e){var i=e||function(e){return t.isBlock(e)||Kn(e)||Gn(e)},a=function(e,t,n,r){if(Vn(e)){var o=r(e,t,e.data);if(-1!==o)return ve.some({container:e,offset:o})}return n().bind(function(e){return a(e.container,e.offset,n,r)})};return{backwards:function(e,t,n,r){var o=_u(e,r,i);return a(e,t,function(){return o.prev().map(function(e){return{container:e,offset:e.length}})},n).getOrNull()},forwards:function(e,t,n,r){var o=_u(e,r,i);return a(e,t,function(){return o.next().map(function(e){return{container:e,offset:0}})},n).getOrNull()}}}function Ru(e){return e?{left:Gu(e.left),top:Gu(e.top),bottom:Gu(e.bottom),right:Gu(e.right),width:Gu(e.width),height:Gu(e.height)}:{left:0,top:0,bottom:0,right:0,width:0,height:0}}function Du(e,t){return e=Ru(e),t||(e.left=e.left+e.width),e.right=e.left,e.width=0,e}function Tu(e,t,n){return 0<=e&&e<=Math.min(t.height,n.height)/2}function Ou(e,t){var n=Math.min(t.height/2,e.height/2);return e.bottom-n<t.top||!(e.top>t.bottom)&&Tu(t.top-e.bottom,e,t)}function Bu(e,t){return e.top>t.bottom||!(e.bottom<t.top)&&Tu(t.bottom-e.top,e,t)}function Pu(e,t,n){return t>=e.left&&t<=e.right&&n>=e.top&&n<=e.bottom}function Lu(e){var t=e.startContainer,n=e.startOffset;return t.hasChildNodes()&&e.endOffset===n+1?t.childNodes[n]:null}function Iu(e,t){if(Hn(e)&&e.hasChildNodes()){var n=e.childNodes;return n[r=n.length-1,Math.min(Math.max(t,0),r)]}return e;var r}function Mu(e){return"string"==typeof e&&768<=e.charCodeAt(0)&&Ju.test(e)}function Fu(e){return"createRange"in e?e.createRange():eu.DOM.createRng()}function Uu(e){return e&&/[\r\n\t ]/.test(e)}function zu(e){return e.setStart&&e.setEnd}function Hu(e){var t=e.startContainer,n=e.startOffset;if(Uu(e.toString())&&rs(t.parentNode)&&Vn(t)){var r=t.data;return Uu(r[n-1])||Uu(r[n+1])?1:void 0}}function ju(e){return 0===e.left&&0===e.right&&0===e.top&&0===e.bottom}function Vu(e,t){var n=Du(e,t);return n.width=1,n.right=n.left+1,n}fu.languageLoad=!0,fu.baseURL="",fu.PluginManager=fu(),fu.ThemeManager=fu();var qu=function(e,t){var n=[];return Y(Tn(e),function(e){n=(n=t(e)?n.concat([e]):n).concat(qu(e,t))}),n},$u=J("mce-annotation"),Wu=J("data-mce-annotation"),Ku=J("data-mce-annotation-uid"),Xu=function(e,t){return yu(Et.fromDom(e.getBody()),"["+Ku()+'="'+t+'"]')},Yu=0,Gu=Math.round,Ju=new RegExp("[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62-\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62-\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1abe\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20dd-\u20e0\u20e1\u20e2-\u20e4\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\ua670-\ua672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]"),Qu=Hn,Zu=Vr,es=an("display","block table"),ts=an("float","left right"),ns=function(){for(var n=[],e=0;e<arguments.length;e++)n[e]=arguments[e];return function(e){for(var t=0;t<n.length;t++)if(!n[t](e))return!1;return!0}}(Qu,Zu,s(ts)),rs=s(an("white-space","pre pre-line pre-wrap")),os=Vn,is=Kn,as=eu.nodeIndex,us=function(e,t){if(!(t<0&&Hn(e)&&e.hasChildNodes()))return Iu(e,t)},ss=function(e){var t=e.getClientRects(),n=0<t.length?Ru(t[0]):Ru(e.getBoundingClientRect());return!zu(e)&&is(e)&&ju(n)?function(e){var t=e.ownerDocument,n=Fu(t),r=t.createTextNode(wo),o=e.parentNode;o.insertBefore(r,e),n.setStart(r,0),n.setEnd(r,1);var i=Ru(n.getBoundingClientRect());return o.removeChild(r),i}(e):ju(n)&&zu(e)?function(e){var t=e.startContainer,n=e.endContainer,r=e.startOffset,o=e.endOffset;if(t===n&&Vn(n)&&0===r&&1===o){var i=e.cloneRange();return i.setEndAfter(n),ss(i)}return null}(e):n},cs=function(t,n,e){function r(){return e=e||function(e){function r(e){var t;0!==e.height&&(0<o.length&&(t=o[o.length-1],e.left===t.left&&e.top===t.top&&e.bottom===t.bottom&&e.right===t.right)||o.push(e))}function t(e,t){var n=Fu(e.ownerDocument);if(t<e.data.length){if(Mu(e.data[t]))return o;if(Mu(e.data[t-1])&&(n.setStart(e,t),n.setEnd(e,t+1),!Hu(n)))return r(Vu(ss(n),!1)),o}0<t&&(n.setStart(e,t-1),n.setEnd(e,t),Hu(n)||r(Vu(ss(n),!1))),t<e.data.length&&(n.setStart(e,t),n.setEnd(e,t+1),Hu(n)||r(Vu(ss(n),!0)))}var o=[],n=e.container(),i=e.offset();if(os(n))return t(n,i),o;if(Qu(n))if(e.isAtEnd()){var a=us(n,i);os(a)&&t(a,a.data.length),ns(a)&&!is(a)&&r(Vu(ss(a),!1))}else{if(a=us(n,i),os(a)&&t(a,0),ns(a)&&e.isAtEnd())return r(Vu(ss(a),!1)),o;var u=us(e.container(),e.offset()-1);ns(u)&&!is(u)&&(!es(u)&&!es(a)&&ns(a)||r(Vu(ss(u),!1))),ns(a)&&r(Vu(ss(a),!0))}return o}(cs(t,n))}return{container:J(t),offset:J(n),toRange:function(){var e=Fu(t.ownerDocument);return e.setStart(t,n),e.setEnd(t,n),e},getClientRects:r,isVisible:function(){return 0<r().length},isAtStart:function(){return os(t),0===n},isAtEnd:function(){return os(t)?n>=t.data.length:n>=t.childNodes.length},isEqual:function(e){return e&&t===e.container()&&n===e.offset()},getNode:function(e){return us(t,e?n-1:n)}}};function ls(e,t){Vn(t)&&0===t.data.length&&e.remove(t)}function fs(e,t,n){var r,o,i,a,u,s,c;Wn(n)?(i=e,a=t,s=ve.from((u=n).firstChild),c=ve.from(u.lastChild),a.insertNode(u),s.each(function(e){return ls(i,e.previousSibling)}),c.each(function(e){return ls(i,e.nextSibling)})):(r=e,t.insertNode(o=n),ls(r,o.previousSibling),ls(r,o.nextSibling))}function ds(t){return function(e){return t===e}}function ms(e){var t,r,n,o;return(lc(e)?"text()":e.nodeName.toLowerCase())+"["+(r=gc(mc(t=e)),n=ge(r,ds(t),t),o=me(r=r.slice(0,n+1),function(e,t,n){return lc(t)&&lc(r[n-1])&&e++,e},0),ge(r=fe(r,on([t.nodeName])),ds(t),t)-o)+"]"}function gs(e,t){var n,r,o,i=[],a=t.container(),u=t.offset();return lc(a)?n=function(e,t){for(;(e=e.previousSibling)&&lc(e);)t+=e.data.length;return t}(a,u):(u>=(r=a.childNodes).length?(n="after",u=r.length-1):n="before",a=r[u]),i.push(ms(a)),o=fe(function(e,t){var n=[];for(t=t.parentNode;t!==e;t=t.parentNode)n.push(t);return n}(e,a),s(sn)),(i=i.concat(le(o,ms))).reverse().join("/")+","+n}function ps(e,t){if(!t)return null;var n=t.split(","),r=n[0].split("/"),o=1<n.length?n[1]:"before",i=me(r,function(e,t){var n,r,o,i,a=/([\w\-\(\)]+)\[([0-9]+)\]/.exec(t);return a?("text()"===a[1]&&(a[1]="#text"),n=e,r=a[1],o=parseInt(a[2],10),i=fe(i=gc(n),function(e,t){return!lc(e)||!lc(i[t-1])}),(i=fe(i,on([r])))[o]):null},e);return i?lc(i)?function(e,t){for(var n,r=e,o=0;lc(r);){if(n=r.data.length,o<=t&&t<=o+n){e=r,t-=o;break}if(!lc(r.nextSibling)){e=r,t=n;break}o+=n,r=r.nextSibling}return lc(e)&&t>e.data.length&&(t=e.data.length),cs(e,t)}(i,parseInt(o,10)):(o="after"===o?dc(i)+1:dc(i),cs(i.parentNode,o)):null}function hs(e,t,n,r,o){var i,a=r[o?"startContainer":"endContainer"],u=r[o?"startOffset":"endOffset"],s=[],c=0,l=e.getRoot();for(Vn(a)?s.push(n?function(e,t,n){for(var r=e(t.data.slice(0,n)).length,o=t.previousSibling;o&&Vn(o);o=o.previousSibling)r+=e(o.data).length;return r}(t,a,u):u):(u>=(i=a.childNodes).length&&i.length&&(c=1,u=Math.max(0,i.length-1)),s.push(e.nodeIndex(i[u],n)+c));a&&a!==l;a=a.parentNode)s.push(e.nodeIndex(a,n));return s}function vs(e,t,n){var r=0;return Nt.each(e.select(t),function(e){if("all"!==e.getAttribute("data-mce-bogus"))return e!==n&&void r++}),r}function bs(e,t){var n,r=t?"start":"end",o=e[r+"Container"],i=e[r+"Offset"];Hn(o)&&"TR"===o.nodeName&&(o=(n=o.childNodes)[Math.min(t?i:i-1,n.length-1)])&&(i=t?0:o.childNodes.length,e["set"+(t?"Start":"End")](o,i))}function ys(e){return bs(e,!0),bs(e,!1),e}function Cs(e,t){var n;return Hn(e)&&(e=Iu(e,t),pc(e))?e:Mr(e)?(n=(e=Vn(e)&&Lr(e)?e.parentNode:e).previousSibling,pc(n)?n:(n=e.nextSibling,pc(n)?n:void 0)):void 0}function xs(e,t,n){var r=n.getNode(),o=r?r.nodeName:null,i=n.getRng();if(pc(r)||"IMG"===o)return{name:o,index:vs(n.dom,o,r)};var a,u,s,c,l,f,d,m=Cs((a=i).startContainer,a.startOffset)||Cs(a.endContainer,a.endOffset);return m?{name:o=m.tagName,index:vs(n.dom,o,m)}:(f=(s=n).dom,(d={}).start=hs(f,u=e,c=t,l=i,!0),s.isCollapsed()||(d.end=hs(f,u,c,l,!1)),jr(l)&&(d.isFakeCaret=!0),d)}function ws(e,t,n){var r={"data-mce-type":"bookmark",id:t,style:"overflow:hidden;line-height:0px"};return n?e.create("span",r,""):e.create("span",r)}function Ss(e,t){var n=e.dom,r=e.getRng(),o=n.uniqueId(),i=e.isCollapsed(),a=e.getNode(),u=a.nodeName;if("IMG"===u)return{name:u,index:vs(n,u,a)};var s=ys(r.cloneRange());return i||(s.collapse(!1),fs(n,s,ws(n,o+"_end",t))),(r=ys(r)).collapse(!0),fs(n,r,ws(n,o+"_start",t)),e.moveToBookmark({id:o,keep:!0}),{id:o}}function Ns(e,t,n){var r=e.getParam(t,n);return-1===r.indexOf("=")?r:ue(e.getParam(t,"","hash"),e.id).getOr(n)}function Es(e){return e.getParam("content_security_policy","")}function ks(e){if(e.getParam("force_p_newlines",!1))return"p";var t=e.getParam("forced_root_block","p");return!1===t?"":!0===t?"p":t}function _s(e){return e.getParam("forced_root_block_attrs",{})}function As(e){return e.getParam("automatic_uploads",!0,"boolean")}function Rs(e){return e.getParam("icons","","string")}function Ds(e){return e.getParam("referrer_policy","","string")}function Ts(e){return e.getParam("language","en","string")}function Os(e){return e.getParam("indent_use_margin",!1)}function Bs(e){var t=e.getParam("font_css",[]);return S(t)?t:A(t.split(","),Je)}function Ps(e){var t=e.getParam("object_resizing");return!1!==t&&!xt.iOS&&(X(t)?t:"table,img,figure.image,div,video,iframe")}function Ls(e){return e.getParam("event_root")}function Is(e){return e.getParam("theme")}function Ms(e){return!1!==e.getParam("inline_boundaries")}function Fs(e){return e.getParam("plugins","","string")}function Us(e){var t=e.parentNode;t&&t.removeChild(e)}function zs(e){var t=Eo(e);return{count:e.length-t.length,text:t}}function Hs(e){for(var t;-1!==(t=e.data.lastIndexOf(So));)e.deleteData(t,1)}function js(e,t){return Cc(e),t}function Vs(e,t){var n,r=t.container(),o=(-1===(n=_(xe(r.childNodes),e))?ve.none():ve.some(n)).map(function(e){return e<t.offset()?cs(r,t.offset()-1):t}).getOr(t);return Cc(e),o}function qs(e,t){return cs.isTextPosition(t)?(r=t,yc(n=e)&&r.container()===n?(a=zs((o=n).data.substr(0,(i=r).offset())),u=zs(o.data.substr(i.offset())),0<(a.text+u.text).length?(Hs(o),cs(o,i.offset()-a.count)):i):js(n,r)):(s=e,((c=t).container()===s.parentNode?Vs:js)(s,c));var n,r,o,i,a,u,s,c}function $s(e,t,n){var r,o,i,a=Du(t.getBoundingClientRect(),n),u="BODY"===e.tagName?(r=e.ownerDocument.documentElement,o=e.scrollLeft||r.scrollLeft,e.scrollTop||r.scrollTop):(i=e.getBoundingClientRect(),o=e.scrollLeft-i.left,e.scrollTop-i.top);a.left+=o,a.right+=o,a.top+=u,a.bottom+=u,a.width=1;var s=t.offsetWidth-t.clientWidth;return 0<s&&(n&&(s*=-1),a.left+=s,a.right+=s),a}function Ws(e,i,a,u){function s(){!function(){for(var e=yu(Et.fromDom(i),"*[contentEditable=false],video,audio,embed,object"),t=0;t<e.length;t++){var n,r=e[t].dom,o=r.previousSibling;Ro(o)&&(1===(n=o.data).length?o.parentNode.removeChild(o):o.deleteData(n.length-1,1)),o=r.nextSibling,Ao(o)&&(1===(n=o.data).length?o.parentNode.removeChild(o):o.deleteData(0,1))}}(),l&&(Cc(l),l=null),f.on(function(e){Ya(e.caret).remove(),f.clear()}),c&&(Ar.clearInterval(c),c=void 0)}var c,l,f=du(),t=ks(e),d=0<t.length?t:"p";return{show:function(e,t){var n;if(s(),Nc(t))return null;if(!a(t))return l=function(e,t){var n=e.ownerDocument.createTextNode(So),r=e.parentNode;if(t){if(o=e.previousSibling,_o(o)){if(Mr(o))return o;if(Ro(o))return o.splitText(o.data.length-1)}r.insertBefore(n,e)}else{var o=e.nextSibling;if(_o(o)){if(Mr(o))return o;if(Ao(o))return o.splitText(1),o}e.nextSibling?r.insertBefore(n,e.nextSibling):r.appendChild(n)}return n}(t,e),n=t.ownerDocument.createRange(),Ec(l.nextSibling)?(n.setStart(l,0),n.setEnd(l,0)):(n.setStart(l,1),n.setEnd(l,1)),n;l=function(e,t,n){var r,o=t.ownerDocument.createElement(e);o.setAttribute("data-mce-caret",n?"before":"after"),o.setAttribute("data-mce-bogus","all"),o.appendChild(((r=document.createElement("br")).setAttribute("data-mce-bogus","1"),r));var i=t.parentNode;return n?i.insertBefore(o,t):t.nextSibling?i.insertBefore(o,t.nextSibling):i.appendChild(o),o}(d,t,e);var r=$s(i,t,e);Ya(l).css("top",r.top);var o=Ya('<div class="mce-visual-caret" data-mce-bogus="all"></div>').css(_e({},r)).appendTo(i)[0];return f.set({caret:o,element:t,before:e}),e&&Ya(o).addClass("mce-visual-caret-before"),c=Ar.setInterval(function(){u()?Ya("div.mce-visual-caret",i).toggleClass("mce-visual-caret-hidden"):Ya("div.mce-visual-caret",i).addClass("mce-visual-caret-hidden")},500),(n=t.ownerDocument.createRange()).setStart(l,0),n.setEnd(l,0),n},hide:s,getCss:function(){return".mce-visual-caret {position: absolute;background-color: black;background-color: currentcolor;}.mce-visual-caret-hidden {display: none;}*[data-mce-caret] {position: absolute;left: -1000px;right: auto;top: 0;margin: 0;padding: 0;}"},reposition:function(){f.on(function(e){var t=$s(i,e.element,e.before);Ya(e.caret).css(_e({},t))})},destroy:function(){return Ar.clearInterval(c)}}}function Ks(){return xc.isIE()||xc.isEdge()||xc.isFirefox()}function Xs(e){return Ec(e)||cn(e)&&Ks()}function Ys(e,t){for(var n;n=e(t);)if(!Dc(n))return n;return null}function Gs(e,t,n,r,o){var i=new Dr(e,r),a=kc(e)||Dc(e);if(t<0){if(a&&n(e=Ys(i.prev.bind(i),!0)))return e;for(;e=Ys(i.prev.bind(i),o);)if(n(e))return e}if(0<t){if(a&&n(e=Ys(i.next.bind(i),!0)))return e;for(;e=Ys(i.next.bind(i),o);)if(n(e))return e}return null}function Js(e,t){for(;e&&e!==t;){if(Ac(e))return e;e=e.parentNode}return null}function Qs(e,t,n){return Js(e.container(),n)===Js(t.container(),n)}function Zs(e,t){if(!t)return null;var n=t.container(),r=t.offset();return Tc(n)?n.childNodes[r+e]:null}function ec(e,t){var n=t.ownerDocument.createRange();return e?(n.setStartBefore(t),n.setEndBefore(t)):(n.setStartAfter(t),n.setEndAfter(t)),n}function tc(e,t,n){for(var r,o,i=e?"previousSibling":"nextSibling";n&&n!==t;){var a=n[i];if(Rc(a)&&(a=a[i]),kc(a)||_c(a)){if(o=n,Js(a,r=t)===Js(o,r))return a;break}if(Oc(a))break;n=n.parentNode}return null}function nc(e,t,n){var r,o=R(tc,!0,t),i=R(tc,!1,t),a=n.startContainer,u=n.startOffset;if(Lr(a)){var s=(a=Tc(a)?a:a.parentNode).getAttribute("data-mce-caret");if("before"===s&&Xs(r=a.nextSibling))return Bc(r);if("after"===s&&Xs(r=a.previousSibling))return Pc(r)}if(!n.collapsed)return n;if(Vn(a)){if(Rc(a)){if(1===e){if(r=i(a))return Bc(r);if(r=o(a))return Pc(r)}if(-1===e){if(r=o(a))return Pc(r);if(r=i(a))return Bc(r)}return n}if(Ro(a)&&u>=a.data.length-1)return 1===e&&(r=i(a))?Bc(r):n;if(Ao(a)&&u<=1)return-1===e&&(r=o(a))?Pc(r):n;if(u===a.data.length)return(r=i(a))?Bc(r):n;if(0===u)return(r=o(a))?Pc(r):n}return n}function rc(e,t){return ve.from(Zs(e?0:-1,t)).filter(kc)}function oc(e,t,n){var r=nc(e,t,n);return-1===e?cs.fromRangeStart(r):cs.fromRangeEnd(r)}function ic(e){return ve.from(e.getNode()).map(Et.fromDom)}function ac(e,t){for(;t=e(t);)if(t.isVisible())return t;return t}function uc(e,t){var n=Qs(e,t);return!(n||!Kn(e.getNode()))||n}cs.fromRangeStart=function(e){return cs(e.startContainer,e.startOffset)},cs.fromRangeEnd=function(e){return cs(e.endContainer,e.endOffset)},cs.after=function(e){return cs(e.parentNode,as(e)+1)},cs.before=function(e){return cs(e.parentNode,as(e))},cs.isAbove=function(e,t){return dn(Q(t.getClientRects()),Z(e.getClientRects()),Ou).getOr(!1)},cs.isBelow=function(e,t){return dn(Z(t.getClientRects()),Q(e.getClientRects()),Bu).getOr(!1)},cs.isAtStart=function(e){return!!e&&e.isAtStart()},cs.isAtEnd=function(e){return!!e&&e.isAtEnd()},cs.isTextPosition=function(e){return!!e&&Vn(e.container())},cs.isElementPosition=function(e){return!1===cs.isTextPosition(e)};var sc,cc,lc=Vn,fc=sn,dc=eu.nodeIndex,mc=function(e){var t=e.parentNode;return fc(t)?mc(t):t},gc=function(e){return e?me(e.childNodes,function(e,t){return fc(t)&&"BR"!==t.nodeName?e=e.concat(gc(t)):e.push(t),e},[]):[]},pc=Gn,hc=R(xs,u,!0),vc=eu.DOM,bc=Hn,yc=Vn,Cc=function(e){bc(e)&&Mr(e)&&(Fr(e)?e.removeAttribute("data-mce-caret"):Us(e)),yc(e)&&(Hs(e),0===e.data.length&&Us(e))},xc=dt().browser,wc=Gn,Sc=Qn,Nc=Jn,Ec=function(e){return wc(e)||Sc(e)},kc=Gn,_c=Qn,Ac=an("display","block table table-cell table-caption list-item"),Rc=Mr,Dc=Lr,Tc=Hn,Oc=Vr,Bc=R(ec,!0),Pc=R(ec,!1);function Lc(e,t){return e.hasChildNodes()&&t<e.childNodes.length?e.childNodes[t]:null}function Ic(e,t){if(0<e){if(Gl(t.previousSibling)&&!Kl(t.previousSibling))return cs.before(t);if(Kl(t))return cs(t,0)}if(e<0){if(Gl(t.nextSibling)&&!Kl(t.nextSibling))return cs.after(t);if(Kl(t))return cs(t,t.data.length)}return e<0&&!Yl(t)?cs.after(t):cs.before(t)}function Mc(t){return{next:function(e){return Ql(sc.Forwards,e,t)},prev:function(e){return Ql(sc.Backwards,e,t)}}}function Fc(e){return cs.isTextPosition(e)?0===e.offset():Vr(e.getNode())}function Uc(e){if(cs.isTextPosition(e)){var t=e.container();return e.offset()===t.data.length}return Vr(e.getNode(!0))}function zc(e,t){return!cs.isTextPosition(e)&&!cs.isTextPosition(t)&&e.getNode()===t.getNode(!0)}function Hc(o,i,a){return Zl(o,i,a).bind(function(e){return Qs(a,e,i)&&(t=a,n=e,o?!zc(t,n)&&(cs.isTextPosition(r=t)||!Kn(r.getNode()))&&Uc(t)&&Fc(n):!zc(n,t)&&Fc(t)&&Uc(n))?Zl(o,i,e):ve.some(e);var t,n,r})}function jc(e,t){var n,r,o,i,a,u=e?t.firstChild:t.lastChild;return Vn(u)?ve.some(cs(u,e?0:u.data.length)):u?Vr(u)?ve.some(e?cs.before(u):Kn(a=u)?cs.before(a):cs.after(a)):(r=t,o=u,i=(n=e)?cs.before(o):cs.after(o),Zl(n,r,i)):ve.none()}function Vc(e){return Hn(e)&&e.id===af}function qc(e,t){for(;t&&t!==e;){if(t.id===af)return t;t=t.parentNode}return null}function $c(e){return Nt.isArray(e.start)}function Wc(e,t){return Hn(t)&&e.isBlock(t)&&!t.innerHTML&&!xt.ie&&(t.innerHTML='<br data-mce-bogus="1" />'),t}function Kc(e,t,n){return!1===t.hasChildNodes()&&qc(e,t)&&(o=n,i=(r=t).ownerDocument.createTextNode(So),r.appendChild(i),o.setStart(i,0),o.setEnd(i,0),1);var r,o,i}function Xc(e,t,n,r){var o,i,a,u,s=n[t?"start":"end"],c=e.getRoot();if(s){for(a=s[0],i=c,o=s.length-1;1<=o;o--){if(u=i.childNodes,Kc(c,i,r))return 1;if(s[o]>u.length-1)return Kc(c,i,r)||function(t){return of(i).fold(D,function(e){return t.setStart(e.container(),e.offset()),t.setEnd(e.container(),e.offset()),!0})}(r);i=u[s[o]]}3===i.nodeType&&(a=Math.min(s[0],i.nodeValue.length)),1===i.nodeType&&(a=Math.min(s[0],i.childNodes.length)),t?r.setStart(i,a):r.setEnd(i,a)}return 1}function Yc(e){return Vn(e)&&0<e.data.length}function Gc(e,t,n){var r,o,i,a,u,s,c=e.get(n.id+"_"+t),l=n.keep;if(c){if(r=c.parentNode,o="start"===t?l?c.hasChildNodes()?(r=c.firstChild,1):Yc(c.nextSibling)?(r=c.nextSibling,0):Yc(c.previousSibling)?(r=c.previousSibling,c.previousSibling.data.length):(r=c.parentNode,e.nodeIndex(c)+1):e.nodeIndex(c):l?c.hasChildNodes()?(r=c.firstChild,1):Yc(c.previousSibling)?(r=c.previousSibling,c.previousSibling.data.length):(r=c.parentNode,e.nodeIndex(c)):e.nodeIndex(c),u=r,s=o,!l){for(a=c.previousSibling,i=c.nextSibling,Nt.each(Nt.grep(c.childNodes),function(e){Vn(e)&&(e.nodeValue=e.nodeValue.replace(/\uFEFF/g,""))});c=e.get(n.id+"_"+t);)e.remove(c,!0);a&&i&&a.nodeType===i.nodeType&&Vn(a)&&!xt.opera&&(o=a.nodeValue.length,a.appendData(i.nodeValue),e.remove(i),u=a,s=o)}return ve.some(cs(u,s))}return ve.none()}function Jc(t,e){!function(e,t){var n,r,o,i,a,u,s,c,l,f,d,m,g=e.dom;if(t){if($c(t))return d=t,m=(f=g).createRng(),Xc(f,!0,d,m)&&Xc(f,!1,d,m)?ve.some(m):ve.none();if(X(t.start))return ve.some((s=t,c=(u=g).createRng(),l=ps(u.getRoot(),s.start),c.setStart(l.container(),l.offset()),l=ps(u.getRoot(),s.end),c.setEnd(l.container(),l.offset()),c));if(Ee(t,"id"))return dn(a=Gc(o=g,"start",i=t),Gc(o,"end",i).or(a),function(e,t){var n=o.createRng();return n.setStart(Wc(o,e.container()),e.offset()),n.setEnd(Wc(o,t.container()),t.offset()),n});if(Ee(t,"name"))return n=g,ve.from(n.select((r=t).name)[r.index]).map(function(e){var t=n.createRng();return t.selectNode(e),t});if(Ee(t,"rng"))return ve.some(t.rng)}return ve.none()}(t,e).each(function(e){t.setRng(e)})}function Qc(e){return Hn(e)&&"SPAN"===e.tagName&&"bookmark"===e.getAttribute("data-mce-type")}function Zc(e){return""!==e&&-1!==" \f\n\r\t\v".indexOf(e)}function el(e){return!Zc(e)&&!sf(e)}function tl(e){return e.nodeType}function nl(e,t,n){var r,o=n.startOffset,i=n.startContainer;if((i!==n.endContainer||!(r=i.childNodes[o])||!/^(IMG)$/.test(r.nodeName))&&Hn(i)){var a=i.childNodes,u=void 0;o<a.length?(i=a[o],u=new Dr(i,e.getParent(i,e.isBlock))):(i=a[a.length-1],(u=new Dr(i,e.getParent(i,e.isBlock))).next(!0));for(var s=u.current();s;s=u.next())if(Vn(s)&&!cf(s))return n.setStart(s,0),t.setRng(n),0}}function rl(e,t,n){if(e){var r=t?"nextSibling":"previousSibling";for(e=n?e:e[r];e;e=e[r])if(Hn(e)||!cf(e))return e}}function ol(e,t){return tl(t)&&(t=t.nodeName),!!e.schema.getTextBlockElements()[t.toLowerCase()]}function il(e,t,n){return e.schema.isValidChild(t,n)}function al(e,n){return y(e)?e=e(n):V(n)&&(e=e.replace(/%(\w+)/g,function(e,t){return n[t]||e})),e}function ul(e,t){return e=""+((e=e||"").nodeName||e),t=""+((t=t||"").nodeName||t),e.toLowerCase()===t.toLowerCase()}function sl(e,t,n){return"color"!==n&&"backgroundColor"!==n||(t=e.toHex(t)),"fontWeight"===n&&700===t&&(t="bold"),""+("fontFamily"===n?t.replace(/[\'\"]/g,"").replace(/,\s+/g,","):t)}function cl(e,t,n){return sl(e,e.getStyle(t,n),n)}function ll(t,e){var n;return t.getParent(e,function(e){return(n=t.getStyle(e,"text-decoration"))&&"none"!==n}),n}function fl(e,t,n){return e.getParents(t,n,e.getRoot())}function dl(e,t){return F(e.formatter.get(t),function(t){function o(e){return 1<e.length&&"%"===e.charAt(0)}return F(["styles","attributes"],function(e){return ue(t,e).exists(function(e){var n,r;return F(S(e)?e:(n=u,r=[],ne(e,function(e,t){r.push(n(e,t))}),r),o)})})})}function ml(e){return se(e,"block")}function gl(e){return se(e,"selector")}function pl(e){return se(e,"inline")}function hl(e){return gl(e)&&!1!==e.expand&&!pl(e)}function vl(e,t){for(var n=t;n;){if(Hn(n)&&e.getContentEditable(n))return"false"===e.getContentEditable(n)?n:t;n=n.parentNode}return t}function bl(e,t,n,r){for(var o=t.data,i=n;e?0<=i:i<o.length;e?i--:i++)if(r(o.charAt(i)))return e?i+1:i;return-1}function yl(e,t,n){return bl(e,t,n,function(e){return sf(e)||Zc(e)})}function Cl(e,t,n){return bl(e,t,n,el)}function xl(i,e,t,n,a,r){function o(e,t,n){var r=Au(i),o=a?r.backwards:r.forwards;return ve.from(o(e,t,function(e,t){return lf(e.parentNode)?-1:n(a,u=e,t)},s))}var u,s=i.getParent(t,i.isBlock)||e;return o(t,n,yl).bind(function(e){return r?o(e.container,e.offset+(a?-1:0),Cl):ve.some(e)}).orThunk(function(){return u?ve.some({container:u,offset:a?0:u.length}):ve.none()})}function wl(e,t,n,r,o){Vn(r)&&Pe(r.data)&&r[o]&&(r=r[o]);for(var i=ff(e,r),a=0;a<i.length;a++)for(var u=0;u<t.length;u++){var s=t[u];if((!V(s.collapsed)||s.collapsed===n.collapsed)&&gl(s)&&e.is(i[a],s.selector))return i[a]}return r}function Sl(t,e,n,r){var o,i=n,a=t.dom,u=a.getRoot(),s=e[0];if((i=ml(s)?s.wrapper?null:a.getParent(n,s.block,u):i)||(o=a.getParent(n,"LI,TD,TH"),i=a.getParent(Vn(n)?n.parentNode:n,function(e){return e!==u&&mf(t,e)},o)),!(i=i&&ml(s)&&s.wrapper&&ff(a,i,"ul,ol").reverse()[0]||i))for(i=n;i[r]&&!a.isBlock(i[r])&&!ul(i=i[r],"br"););return i||n}function Nl(e,t,n,r,o){var i,a=n,u=o?"previousSibling":"nextSibling",s=e.getRoot();if(Vn(n)&&!df(n)&&(o?0<r:r<n.data.length))return n;for(;;){if(!t[0].block_expand&&e.isBlock(a))return a;for(var c=a[u];c;c=c[u]){var l=Vn(c)&&!gf(e,s,c,u);if(!lf(c)&&(!Kn(i=c)||!i.getAttribute("data-mce-bogus")||i.nextSibling)&&!df(c,l))return a}if(a===s||a.parentNode===s){n=a;break}a=a.parentNode}return n}function El(e){return lf(e.parentNode)||lf(e)}function kl(e,t,n,r){void 0===r&&(r=!1);var o=t.startContainer,i=t.startOffset,a=t.endContainer,u=t.endOffset,s=e.dom,c=n[0];return Hn(o)&&o.hasChildNodes()&&(o=Iu(o,i),Vn(o)&&(i=0)),Hn(a)&&a.hasChildNodes()&&(a=Iu(a,t.collapsed?u:u-1),Vn(a)&&(u=a.nodeValue.length)),o=vl(s,o),a=vl(s,a),El(o)&&(o=lf(o)?o:o.parentNode,o=t.collapsed?o.previousSibling||o:o.nextSibling||o,Vn(o)&&(i=t.collapsed?o.length:0)),El(a)&&(a=lf(a)?a:a.parentNode,a=t.collapsed?a.nextSibling||a:a.previousSibling||a,Vn(a)&&(u=t.collapsed?0:a.length)),t.collapsed&&(xl(s,e.getBody(),o,i,!0,r).each(function(e){var t=e.container,n=e.offset;o=t,i=n}),xl(s,e.getBody(),a,u,!1,r).each(function(e){var t=e.container,n=e.offset;a=t,u=n})),(pl(c)||c.block_expand)&&(pl(c)&&Vn(o)&&0!==i||(o=Nl(s,n,o,i,!0)),pl(c)&&Vn(a)&&u!==a.nodeValue.length||(a=Nl(s,n,a,u,!1))),hl(c)&&(o=wl(s,n,t,o,"previousSibling"),a=wl(s,n,t,a,"nextSibling")),(ml(c)||gl(c))&&(o=Sl(e,n,o,"previousSibling"),a=Sl(e,n,a,"nextSibling"),ml(c)&&(s.isBlock(o)||(o=Nl(s,n,o,i,!0)),s.isBlock(a)||(a=Nl(s,n,a,u,!1)))),Hn(o)&&(i=s.nodeIndex(o),o=o.parentNode),Hn(a)&&(u=s.nodeIndex(a)+1,a=a.parentNode),{startContainer:o,startOffset:i,endContainer:a,endOffset:u}}function _l(n,e,u){function s(e){var t=e[0];Vn(t)&&t===i&&o>=t.data.length&&e.splice(0,1);var n=e[e.length-1];return 0===a&&0<e.length&&n===l&&Vn(n)&&e.splice(e.length-1,1),e}function c(e,t,n){for(var r=[];e&&e!==n;e=e[t])r.push(e);return r}function t(e,t){return n.getParent(e,function(e){return e.parentNode===t},t)}function r(e,t,n){var r=n?"nextSibling":"previousSibling",o=e;for(o.parentNode;o&&o!==t;o=i){var i=o.parentNode,a=c(o===e?o:o[r],r);a.length&&(n||a.reverse(),u(s(a)))}}var o=e.startOffset,i=Iu(e.startContainer,o),a=e.endOffset,l=Iu(e.endContainer,a-1);if(i===l)return u(s([i]));var f=n.findCommonAncestor(i,l);if(n.isChildOf(i,l))return r(i,f,!0);if(n.isChildOf(l,i))return r(l,f);var d=t(i,f)||i,m=t(l,f)||l;r(i,d,!0);var g=c(d===i?d:d.nextSibling,"nextSibling",m===l?m.nextSibling:m);g.length&&u(s(g)),r(l,m)}function Al(e){var t=[];if(e)for(var n=0;n<e.rangeCount;n++)t.push(e.getRangeAt(n));return t}function Rl(e,t){var n=yu(t,"td[data-mce-selected],th[data-mce-selected]");return 0<n.length?n:U(H(e,function(e){var t=Lu(e);return t?[Et.fromDom(t)]:[]}),yo)}function Dl(e){return Rl(Al(e.selection.getSel()),Et.fromDom(e.getBody()))}function Tl(e,t){return vr(e,"table",t)}function Ol(o,e){return dn((r=e.startContainer,i=e.startOffset,Vn(r)?0===i?ve.some(Et.fromDom(r)):ve.none():ve.from(r.childNodes[i]).map(Et.fromDom)),(t=e.endContainer,n=e.endOffset,Vn(t)?n===t.data.length?ve.some(Et.fromDom(t)):ve.none():ve.from(t.childNodes[n-1]).map(Et.fromDom)),function(e,t){var n=M(pf(o),R(je,e)),r=M(hf(o),R(je,t));return n.isSome()&&r.isSome()}).getOr(!1);var t,n,r,i}function Bl(e,t,n,r){var o=n,i=new Dr(n,o),a=ae(e.schema.getMoveCaretBeforeOnEnterElements(),function(e,t){return!T(["td","th","table"],t.toLowerCase())});do{if(Vn(n)&&0!==Nt.trim(n.nodeValue).length)return r?t.setStart(n,0):t.setEnd(n,n.nodeValue.length),0;if(a[n.nodeName])return r?t.setStartBefore(n):"BR"===n.nodeName?t.setEndBefore(n):t.setEndAfter(n),0}while(n=r?i.next():i.prev());"BODY"===o.nodeName&&(r?t.setStart(o,0):t.setEnd(o,o.childNodes.length))}function Pl(e){var t=e.selection.getSel();return t&&0<t.rangeCount}function Ll(r,o){var e=Dl(r);0<e.length?Y(e,function(e){var t=e.dom,n=r.dom.createRng();n.setStartBefore(t),n.setEndAfter(t),o(n,!0)}):o(r.selection.getRng(),!1)}function Il(e,t,n){var r=Ss(e,t);n(r),e.moveToBookmark(r)}function Ml(e){return vf.get(e)}function Fl(e,t,n,r){var o=t.uid,i=void 0===o?wu("mce-annotation"):o,a=function(e,t){var n={};for(o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(n[o]=e[o]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var r=0,o=Object.getOwnPropertySymbols(e);r<o.length;r++)t.indexOf(o[r])<0&&Object.prototype.propertyIsEnumerable.call(e,o[r])&&(n[o[r]]=e[o[r]]);return n}(t,["uid"]),u=Et.fromTag("span",e);vu(u,$u()),pn(u,""+Ku(),i),pn(u,""+Wu(),n);var s,c=r(i,a),l=c.attributes,f=c.classes,d=void 0===f?[]:f;return hn(u,void 0===l?{}:l),s=u,Y(d,function(e){vu(s,e)}),u}function Ul(u,e,t,n,r){function s(){d.clear()}function c(e){Y(e,o)}var l=[],f=Fl(u.getDoc(),r,t,n),d=du(),o=function(e){var t,n,r,o,i,a;switch(r=u,i="span",a=kt(o=e),Ot(o).fold(function(){return"skipping"},function(e){return"br"===a||An(n=o)&&Ml(n)===So?"valid":_n(t=o)&&bu(t,$u())?"existing":Vc(o.dom)?"caret":il(r,i,a)&&il(r,kt(e),i)?"valid":"invalid-child";var t,n})){case"invalid-child":s(),c(Tn(e)),s();break;case"valid":qt(t=e,n=d.get().getOrThunk(function(){var e=Eu(f);return l.push(e),d.set(e),e})),Ln(n,t)}};return _l(u.dom,e,function(e){s(),c(A(e,Et.fromDom))}),l}function zl(o){var n,e,r,i=(n={},{register:function(e,t){n[e]={name:e,settings:t}},lookup:function(e){return ue(n,e).map(function(e){return e.settings})}});r=i,(e=o).on("init",function(){e.serializer.addNodeFilter("span",function(e){Y(e,function(t){ve.from(t.attr(Wu())).bind(r.lookup).each(function(e){!1===e.persistent&&t.unwrap()})})})});var a=xu(o);return{register:function(e,t){i.register(e,t)},annotate:function(t,n){i.lookup(t).each(function(e){var u,s,c,l;s=t,c=e,l=n,(u=o).undoManager.transact(function(){var e,t,n,r,o=u.selection,i=o.getRng(),a=0<Dl(u).length;i.collapsed&&!a&&(n=kl(e=u,t=i,[{inline:"span"}]),t.setStart(n.startContainer,n.startOffset),t.setEnd(n.endContainer,n.endOffset),e.selection.setRng(t)),o.getRng().collapsed&&!a?(Su(r=Fl(u.getDoc(),l,s,c.decorate),wo),o.getRng().insertNode(r.dom),o.select(r.dom)):Il(o,!1,function(){Ll(u,function(e){Ul(u,e,s,c.decorate,l)})})})})},annotationChanged:function(e,t){a.addListener(e,t)},remove:function(e){Cu(o,ve.some(e)).each(function(e){Y(e.elements,Yt)})},getAll:function(e){var t,n,r;return re((t=e,n=yu(Et.fromDom(o.getBody()),"["+Wu()+'="'+t+'"]'),r={},Y(n,function(e){var t=vn(e,Ku()),n=ue(r,t).getOr([]);r[t]=n.concat([e])}),r),function(e){return A(e,function(e){return e.dom})})}}}function Hl(e){return{getBookmark:R(uf,e),moveToBookmark:R(Jc,e)}}(cc=sc=sc||{})[cc.Backwards=-1]="Backwards",cc[cc.Forwards=1]="Forwards";function jl(e){return Lo(e)||!!Fo(t=e)&&!0!==L(xe(t.getElementsByTagName("*")),function(e,t){return e||Do(t)},!1);var t}var Vl,ql,$l,Wl=Gn,Kl=Vn,Xl=Hn,Yl=Kn,Gl=Vr,Jl=qr,Ql=function(e,t,n){var r,o,i;if(!Xl(n)||!t)return null;if(t.isEqual(cs.after(n))&&n.lastChild){if(i=cs.after(n.lastChild),e<0&&Gl(n.lastChild)&&Xl(n.lastChild))return Yl(n.lastChild)?cs.before(n.lastChild):i}else i=t;var a,u,s,c=i.container(),l=i.offset();if(Kl(c)){if(e<0&&0<l)return cs(c,--l);if(0<e&&l<c.length)return cs(c,++l);r=c}else{if(e<0&&0<l&&(f=Lc(c,l-1),Gl(f)))return!jl(f)&&(o=Gs(f,e,Jl,f))?Kl(o)?cs(o,o.data.length):cs.after(o):Kl(f)?cs(f,f.data.length):cs.before(f);if(0<e&&l<c.childNodes.length&&(f=Lc(c,l),Gl(f)))return Yl(f)?(a=n,(s=(u=f).nextSibling)&&Gl(s)?Kl(s)?cs(s,0):cs.before(s):Ql(sc.Forwards,cs.after(u),a)):!jl(f)&&(o=Gs(f,e,Jl,f))?Kl(o)?cs(o,0):cs.before(o):Kl(f)?cs(f,0):cs.after(f);r=f||i.getNode()}if((0<e&&i.isAtEnd()||e<0&&i.isAtStart())&&(r=Gs(r,e,w,n,!0),Jl(r,n)))return Ic(e,r);var f=Gs(r,e,Jl,n),d=pe(U(function(e,t){for(var n=[];e&&e!==t;)n.push(e),e=e.parentNode;return n}(c,n),Wl));return!d||f&&d.contains(f)?f?Ic(e,f):null:0<e?cs.after(d):cs.before(d)},Zl=function(e,t,n){var r=Mc(t);return ve.from(e?r.next(n):r.prev(n))},ef=function(t,n,e,r){return Hc(t,n,e).bind(function(e){return r(e)?ef(t,n,e,r):ve.some(e)})},tf=R(Zl,!0),nf=R(Zl,!1),rf=R(jc,!0),of=R(jc,!1),af="_mce_caret",uf=function(e,t,n){return 2===t?xs(Eo,n,e):3===t?(o=(r=e).getRng(),{start:gs(r.dom.getRoot(),cs.fromRangeStart(o)),end:gs(r.dom.getRoot(),cs.fromRangeEnd(o))}):t?{rng:e.getRng()}:Ss(e,!1);var r,o},sf=(Vl=wo,function(e){return Vl===e}),cf=function(e,t){return void 0===t&&(t=!1),!(!V(e)||!Vn(e))&&$r(t?e.data.replace(/ /g,"\xa0"):e.data)},lf=Qc,ff=fl,df=cf,mf=ol,gf=function(e,t,n,r){var o=n.parentNode;return!V(n[r])&&(!(o!==t&&!K(o)&&!e.isBlock(o))||gf(e,t,o,r))},pf=function(t){return Ft(t).fold(J([t]),function(e){return[t].concat(pf(e))})},hf=function(t){return Ut(t).fold(J([t]),function(e){return"br"===kt(e)?Bt(e).map(function(e){return[t].concat(hf(e))}).getOr([]):[t].concat(hf(e))})},vf=(ql=An,{get:function(e){if(!ql(e))throw new Error("Can only get text value of a text node");return $l(e).getOr("")},getOption:$l=function(e){return ql(e)?ve.from(e.dom.nodeValue):ve.none()},set:function(e,t){if(!ql(e))throw new Error("Can only set raw text value of a text node");e.dom.nodeValue=t}});function bf(e,t){for(;t&&t!==e;){if(Yn(t)||Gn(t))return t;t=t.parentNode}return null}function yf(t,n,e){if(!e.collapsed){if(xt.browser.isIE()&&e.startOffset===e.endOffset-1&&e.startContainer===e.endContainer){var r=e.startContainer.childNodes[e.startOffset];if(Hn(r))return F(r.getClientRects(),function(e){return Pu(e,t,n)})}return F(e.getClientRects(),function(e){return Pu(e,t,n)})}}function Cf(e,t,n){return e.fire(t,n)}function xf(e,t,n,r){return e.fire("FormatApply",{format:t,node:n,vars:r})}function wf(e,t,n,r){return e.fire("FormatRemove",{format:t,node:n,vars:r})}function Sf(r,l){function c(e){return e&&("IMG"===e.nodeName||l.dom.is(e,"figure.image"))}function f(e){return Qn(e)||T.hasClass(e,"mce-preview-object")}function n(e){var t=e.target;!function(e,t){if("longpress"!==e.type&&0!==e.type.indexOf("touch"))return c(e.target)&&!yf(e.clientX,e.clientY,t);var n=e.touches[0];return c(e.target)&&!yf(n.clientX,n.clientY,t)}(e,l.selection.getRng())||e.isDefaultPrevented()||l.selection.select(t)}function d(e){return T.is(e,"figure.image")?[e.querySelector("img")]:T.hasClass(e,"mce-preview-object")&&V(e.firstElementChild)?[e,e.firstElementChild]:[e]}function i(e){var t=Ps(l);return!!t&&"false"!==e.getAttribute("data-mce-resize")&&e!==l.getBody()&&(T.hasClass(e,"mce-preview-object")?ze(Et.fromDom(e.firstElementChild),t):ze(Et.fromDom(e),t))}function a(e,t,n){V(n)&&Y(d(e),function(e){e.style[t]||!l.schema.isValid(e.nodeName.toLowerCase(),t)?T.setStyle(e,t,n):T.setAttrib(e,t,""+n)})}function m(e,t,n){a(e,"width",t),a(e,"height",n)}function g(e){var t,n,r,o,i,a,u=e.screenX-C,s=e.screenY-x;k=u*b[2]+w,_=s*b[3]+S,k=k<5?5:k,_=_<5?5:_,((c(p)||f(p))&&!1!==l.getParam("resize_img_proportional",!0,"boolean")?!If.modifierPressed(e):If.modifierPressed(e))&&(L(u)>L(s)?(_=I(k*N),k=I(_/N)):(k=I(_/N),_=I(k*N))),m(h,k,_),t=b.startPos.x+u,n=b.startPos.y+s,T.setStyles(v,{left:t=0<t?t:0,top:n=0<n?n:0,display:"block"}),v.innerHTML=k+" × "+_,b[2]<0&&h.clientWidth<=k&&T.setStyle(h,"left",void 0+(w-k)),b[3]<0&&h.clientHeight<=_&&T.setStyle(h,"top",void 0+(S-_)),(u=M.scrollWidth-A)+(s=M.scrollHeight-R)!=0&&T.setStyles(v,{left:t-u,top:n-s}),E||(r=p,o=w,i=S,a="corner-"+b.name,l.fire("ObjectResizeStart",{target:r,width:o,height:i,origin:a}),E=!0)}function o(e){function t(e,t){if(e)do{if(e===t)return 1}while(e=e.parentNode)}var n;E||l.removed||(O(T.select("img[data-mce-selected],hr[data-mce-selected]"),function(e){e.removeAttribute(D)}),n="mousedown"===e.type?e.target:r.getNode(),t(n=T.$(n).closest("table,img,figure.image,hr,video,span.mce-preview-object")[0],M)&&(s(),t(r.getStart(!0),n)&&t(r.getEnd(!0),n))?z(n):H())}function u(e){return Mf(bf(l.getBody(),e))}function s(){try{l.getDoc().execCommand("enableObjectResizing",!1,"false")}catch(e){}}var p,h,v,b,y,C,x,w,S,N,E,k,_,A,R,D="data-mce-selected",T=l.dom,O=Nt.each,B=l.getDoc(),P=document,L=Math.abs,I=Math.round,M=l.getBody(),F={nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]},U=function(){var e,t,n,r,o=E;E=!1,o&&(a(p,"width",k),a(p,"height",_)),T.unbind(B,"mousemove",g),T.unbind(B,"mouseup",U),P!==B&&(T.unbind(P,"mousemove",g),T.unbind(P,"mouseup",U)),T.remove(h),T.remove(v),T.remove(y),z(p),o&&(e=p,t=k,n=_,r="corner-"+b.name,l.fire("ObjectResized",{target:e,width:t,height:n,origin:r}),T.setAttrib(p,"style",T.getAttrib(p,"style"))),l.nodeChanged()},z=function(e){j();var t=T.getPos(e,M),a=t.x,u=t.y,n=e.getBoundingClientRect(),s=n.width||n.right-n.left,c=n.height||n.bottom-n.top;p!==e&&(H(),p=e,k=_=0);var r=l.fire("ObjectSelected",{target:e}),o=T.getAttrib(p,D,"1");i(e)&&!r.isDefaultPrevented()?O(F,function(o,i){var e=T.get("mceResizeHandle"+i);e&&T.remove(e),e=T.add(M,"div",{id:"mceResizeHandle"+i,"data-mce-bogus":"all",class:"mce-resizehandle",unselectable:!0,style:"cursor:"+i+"-resize; margin:0; padding:0"}),11===xt.ie&&(e.contentEditable=!1),T.bind(e,"mousedown",function(e){var t,n,r;e.stopImmediatePropagation(),e.preventDefault(),t=e,r=d(p)[0],C=t.screenX,x=t.screenY,w=r.clientWidth,S=r.clientHeight,N=S/w,(b=o).name=i,b.startPos={x:s*o[0]+a,y:c*o[1]+u},A=M.scrollWidth,R=M.scrollHeight,y=T.add(M,"div",{class:"mce-resize-backdrop","data-mce-bogus":"all"}),T.setStyles(y,{position:"fixed",left:"0",top:"0",width:"100%",height:"100%"}),h=f(n=p)?T.create("img",{src:xt.transparentSrc}):n.cloneNode(!0),T.addClass(h,"mce-clonedresizable"),T.setAttrib(h,"data-mce-bogus","all"),h.contentEditable="false",T.setStyles(h,{left:a,top:u,margin:0}),m(h,s,c),h.removeAttribute(D),M.appendChild(h),T.bind(B,"mousemove",g),T.bind(B,"mouseup",U),P!==B&&(T.bind(P,"mousemove",g),T.bind(P,"mouseup",U)),v=T.add(M,"div",{class:"mce-resize-helper","data-mce-bogus":"all"},w+" × "+S)}),o.elm=e,T.setStyles(e,{left:s*o[0]+a-e.offsetWidth/2,top:c*o[1]+u-e.offsetHeight/2})}):H(),T.getAttrib(p,D)||p.setAttribute(D,o)},H=function(){j(),p&&p.removeAttribute(D),ne(F,function(e,t){var n=T.get("mceResizeHandle"+t);n&&(T.unbind(n),T.remove(n))})},j=function(){ne(F,function(e){e.elm&&(T.unbind(e.elm),delete e.elm)})};return l.on("init",function(){var e;s(),(xt.browser.isIE()||xt.browser.isEdge())&&(l.on("mousedown click",function(e){var t=e.target,n=t.nodeName;E||!/^(TABLE|IMG|HR)$/.test(n)||u(t)||(2!==e.button&&l.selection.select(t,"TABLE"===n),"mousedown"===e.type&&l.nodeChanged())}),T.bind(M,"mscontrolselect",e=function(e){function t(e){Ar.setEditorTimeout(l,function(){return l.selection.select(e)})}if(u(e.target)||Qn(e.target))return e.preventDefault(),void t(e.target);/^(TABLE|IMG|HR)$/.test(e.target.nodeName)&&(e.preventDefault(),"IMG"===e.target.tagName&&t(e.target))}),l.on("remove",function(){return T.unbind(M,"mscontrolselect",e)}));var t=Ar.throttle(function(e){l.composing||o(e)});l.on("NodeChange ResizeEditor ResizeWindow ResizeContent drop",t),l.on("keyup compositionend",function(e){p&&"TABLE"===p.nodeName&&t(e)}),l.on("hide blur",H),l.on("contextmenu longpress",n,!0)}),l.on("remove",j),{isResizable:i,showResizeRect:z,hideResizeRect:H,updateResizeRect:o,destroy:function(){p=h=y=null}}}function Nf(e){return Yn(e)||Gn(e)}function Ef(t,n,r){var o,e,i,a,u,s=r;if(s.caretPositionFromPoint)(e=s.caretPositionFromPoint(t,n))&&((o=r.createRange()).setStart(e.offsetNode,e.offset),o.collapse(!0));else if(s.caretRangeFromPoint)o=s.caretRangeFromPoint(t,n);else if(s.body.createTextRange){o=s.body.createTextRange();try{o.moveToPoint(t,n),o.collapse(!0)}catch(e){o=function(e,n,t){var r,o=t.elementFromPoint(e,n),i=t.body.createTextRange();if(o&&"HTML"!==o.tagName||(o=t.body),i.moveToElementText(o),0<(r=(r=Nt.toArray(i.getClientRects())).sort(function(e,t){return(e=Math.abs(Math.max(e.top-n,e.bottom-n)))-Math.abs(Math.max(t.top-n,t.bottom-n))})).length){n=(r[0].bottom+r[0].top)/2;try{return i.moveToPoint(e,n),i.collapse(!0),i}catch(e){}}return null}(t,n,r)}return i=o,a=r.body,u=i&&i.parentElement?i.parentElement():null,Gn(function(e,t,n){for(;e&&e!==t;){if(n(e))return e;e=e.parentNode}return null}(u,a,Nf))?null:i}return o}function kf(e,t){return e&&t&&e.startContainer===t.startContainer&&e.startOffset===t.startOffset&&e.endContainer===t.endContainer&&e.endOffset===t.endOffset}function _f(e,t,n){return null!==function(e,t,n){for(;e&&e!==t;){if(n(e))return e;e=e.parentNode}return null}(e,t,n)}function Af(e){return e&&"TABLE"===e.nodeName}function Rf(e,t,n){for(var r=new Dr(t,e.getParent(t.parentNode,e.isBlock)||e.getRoot());t=r[n?"prev":"next"]();)if(Kn(t))return 1}function Df(e,t,n,r,o){var i,a,u=e.getRoot(),s=e.schema.getNonEmptyElements(),c=e.getParent(o.parentNode,e.isBlock)||u;if(r&&Kn(o)&&t&&e.isEmpty(c))return ve.some(cs(o.parentNode,e.nodeIndex(o)));for(var l,f,d=new Dr(o,c);a=d[r?"prev":"next"]();){if("false"===e.getContentEditableParent(a)||(f=u,Mr(l=a)&&!1===_f(l,f,Vc)))return ve.none();if(Vn(a)&&0<a.nodeValue.length)return!1===_f(a,u,function(e){return"A"===e.nodeName})?ve.some(cs(a,r?a.nodeValue.length:0)):ve.none();if(e.isBlock(a)||s[a.nodeName.toLowerCase()])return ve.none();i=a}return n&&i?ve.some(cs(i,0)):ve.none()}function Tf(e,t,n,r){var o,i=e.getRoot(),a=!1,u=r[(n?"start":"end")+"Container"],s=r[(n?"start":"end")+"Offset"],c=Hn(u)&&s===u.childNodes.length,l=e.schema.getNonEmptyElements(),f=n;if(Mr(u))return ve.none();if(Hn(u)&&s>u.childNodes.length-1&&(f=!1),$n(u)&&(u=i,s=0),u===i){if(f&&(d=u.childNodes[0<s?s-1:0])){if(Mr(d))return ve.none();if(l[d.nodeName]||Af(d))return ve.none()}if(u.hasChildNodes()){if(s=Math.min(!f&&0<s?s-1:s,u.childNodes.length-1),u=u.childNodes[s],s=Vn(u)&&c?u.data.length:0,!t&&u===i.lastChild&&Af(u))return ve.none();if(function(e,t){for(;t&&t!==e;){if(Gn(t))return 1;t=t.parentNode}}(i,u)||Mr(u))return ve.none();if(u.hasChildNodes()&&!1===Af(u)){var d=u,m=new Dr(u,i);do{if(Gn(d)||Mr(d)){a=!1;break}if(Vn(d)&&0<d.nodeValue.length){s=f?0:d.nodeValue.length,u=d,a=!0;break}if(l[d.nodeName.toLowerCase()]&&(!(o=d)||!/^(TD|TH|CAPTION)$/.test(o.nodeName))){s=e.nodeIndex(d),u=d.parentNode,f||s++,a=!0;break}}while(d=f?m.next():m.prev())}}}return t&&(Vn(u)&&0===s&&Df(e,c,t,!0,u).each(function(e){u=e.container(),s=e.offset(),a=!0}),Hn(u)&&(!(d=(d=u.childNodes[s])||u.childNodes[s-1])||!Kn(d)||d.previousSibling&&"A"===d.previousSibling.nodeName||Rf(e,d,!1)||Rf(e,d,!0)||Df(e,c,t,!0,d).each(function(e){u=e.container(),s=e.offset(),a=!0}))),f&&!t&&Vn(u)&&s===u.nodeValue.length&&Df(e,c,t,!1,u).each(function(e){u=e.container(),s=e.offset(),a=!0}),a?ve.some(cs(u,s)):ve.none()}function Of(e,t){var n=t.collapsed,r=t.cloneRange(),o=cs.fromRangeStart(t);return Tf(e,n,!0,r).each(function(e){n&&cs.isAbove(o,e)||r.setStart(e.container(),e.offset())}),n||Tf(e,n,!1,r).each(function(e){r.setEnd(e.container(),e.offset())}),n&&r.collapse(!0),kf(t,r)?ve.none():ve.some(r)}function Bf(e,t){return e.splitText(t)}function Pf(e){var t=e.startContainer,n=e.startOffset,r=e.endContainer,o=e.endOffset;return t===r&&Vn(t)?0<n&&n<t.nodeValue.length&&(t=(r=Bf(t,n)).previousSibling,n<o?(t=r=Bf(r,o-=n).previousSibling,o=r.nodeValue.length,n=0):o=0):(Vn(t)&&0<n&&n<t.nodeValue.length&&(t=Bf(t,n),n=0),Vn(r)&&0<o&&o<r.nodeValue.length&&(o=(r=Bf(r,o).previousSibling).nodeValue.length)),{startContainer:t,startOffset:n,endContainer:r,endOffset:o}}function Lf(n){return{walk:function(e,t){return _l(n,e,t)},split:Pf,normalize:function(t){return Of(n,t).fold(D,function(e){return t.setStart(e.startContainer,e.startOffset),t.setEnd(e.endContainer,e.endOffset),!0})}}}Hl.isBookmarkNode=Qc;var If={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,ESC:27,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,modifierPressed:function(e){return e.shiftKey||e.ctrlKey||e.altKey||If.metaKeyPressed(e)},metaKeyPressed:function(e){return xt.mac?e.metaKey:e.ctrlKey&&!e.altKey}},Mf=Gn;Lf.compareRanges=kf,Lf.getCaretRangeFromPoint=Ef,Lf.getSelectedNode=Lu,Lf.getNode=Iu;var Ff,Uf,zf=(Ff="height",Uf=function(e){var t=e.dom;return Mn(e)?t.getBoundingClientRect().height:t.offsetHeight},{set:function(e,t){if(!N(t)&&!t.match(/^[0-9]+$/))throw new Error(Ff+".set accepts only positive integer values. Value was "+t);var n=e.dom;mn(n)&&(n.style[Ff]=t+"px")},get:Hf,getOuter:Hf,aggregate:jf,max:function(e,t,n){var r=jf(e,n);return r<t?t-r:0}});function Hf(e){var t=Uf(e);if(t<=0||null===t){var n=wn(e,Ff);return parseFloat(n)||0}return t}function jf(o,e){return L(e,function(e,t){var n=wn(o,t),r=void 0===n?0:parseInt(n,10);return isNaN(r)?e:e+r},0)}function Vf(e){return"textarea"===kt(e)}function qf(e,t){var n=function(e){var t=e.dom.ownerDocument,n=t.body,r=t.defaultView,o=t.documentElement;if(n===e.dom)return Un(n.offsetLeft,n.offsetTop);var i=Gt(null==r?void 0:r.pageYOffset,o.scrollTop),a=Gt(null==r?void 0:r.pageXOffset,o.scrollLeft),u=Gt(o.clientTop,n.clientTop),s=Gt(o.clientLeft,n.clientLeft);return zn(e).translate(a-s,i-u)}(e),r=zf.get(e);return{element:e,bottom:n.top+r,height:r,pos:n,cleanup:t}}function $f(n,r,o,i){Od(n,function(e,t){return Td(n,r,o,i)},o)}function Wf(e,t,n,r,o){var i={elm:r.element.dom,alignToTop:o};e.fire("ScrollIntoView",i).isDefaultPrevented()||(n(t,Jt(t).top,r,o),e.fire("AfterScrollIntoView",i))}function Kf(e,t,n,r){var o=Et.fromDom(e.getDoc());Wf(e,o,n,qf(Et.fromDom(t),te),r)}function Xf(e,t,n,r){var o,i=e.pos;n?Qt(i.left,i.top,r):(o=i.top-t+e.height,Qt(i.left,o,r))}function Yf(e,t,n,r,o){var i=n+t,a=r.pos.top,u=r.bottom,s=n<=u-a;a<t?Xf(r,n,!1!==o,e):i<a?Xf(r,n,s?!1!==o:!0===o,e):i<u&&!s&&Xf(r,n,!0===o,e)}function Gf(e,t,n,r){Yf(e,t,e.dom.defaultView.innerHeight,n,r)}function Jf(e,t,n,r){Yf(e,t,e.dom.defaultView.innerHeight,n,r);var o,i,a,u,s,c,l,f=(o=n.element,u=Jt(Et.fromDom(document)),a=(i=Dd).owner(o),s=Rd(i,a),c=zn(o),l=P(s,function(e,t){var n=zn(t);return{left:e.left+n.left,top:e.top+n.top}},{left:0,top:0}),Un(l.left+c.left+u.left,l.top+c.top+u.top)),d=tn(window);f.top<d.y?Zt(n.element,!1!==r):f.top>d.bottom&&Zt(n.element,!0===r)}function Qf(e,t,n){return $f(e,Gf,t,n)}function Zf(e,t,n){return Kf(e,t,Gf,n)}function ed(e,t,n){return $f(e,Jf,t,n)}function td(e,t,n){return Kf(e,t,Jf,n)}function nd(e,t,n){(e.inline?Qf:ed)(e,t,n)}function rd(e){var t=Pn(e).dom;return e.dom===t.activeElement}function od(e){return void 0===e&&(e=Et.fromDom(document)),ve.from(e.dom.activeElement).map(Et.fromDom)}function id(e,t){var n=An(t)?Ml(t).length:Tn(t).length+1;return n<e?n:e<0?0:e}function ad(e){return Id.range(e.start,id(e.soffset,e.start),e.finish,id(e.foffset,e.finish))}function ud(e,t){return!rn(t.dom)&&(Ve(e,t)||je(e,t))}function sd(t){return function(e){return ud(t,e.start)&&ud(t,e.finish)}}function cd(e){return!0===e.inline||Md.isIE()}function ld(e){return Id.range(Et.fromDom(e.startContainer),e.startOffset,Et.fromDom(e.endContainer),e.endOffset)}function fd(e){var t=document.createRange();try{return t.setStart(e.start.dom,e.soffset),t.setEnd(e.finish.dom,e.foffset),ve.some(t)}catch(e){return ve.none()}}function dd(e){var t,n,r=cd(e)?(t=Et.fromDom(e.getBody()),((n=Tt(t).dom.getSelection())&&0!==n.rangeCount?ve.from(n.getRangeAt(0)):ve.none()).map(ld).filter(sd(t))):ve.none();e.bookmark=r.isSome()?r:e.bookmark}function md(n){return(n.bookmark||ve.none()).bind(function(e){return t=Et.fromDom(n.getBody()),ve.from(e).filter(sd(t)).map(ad);var t}).bind(fd)}function gd(u){var s=mu(function(){dd(u)},0);u.on("init",function(){function e(){n.throttle()}var t,n,r,o,i,a;u.inline&&(t=u,n=s,eu.DOM.bind(document,"mouseup",e),t.on("remove",function(){eu.DOM.unbind(document,"mouseup",e)})),r=u,o=s,dt().browser.isIE()?(a=r).on("focusout",function(){dd(a)}):(i=o,r.on("mouseup touchend",function(e){i.throttle()})),r.on("keyup NodeChange",function(e){"nodechange"===e.type&&e.selectionChange||dd(r)})}),u.on("remove",function(){s.cancel()})}function pd(t,e){var n=t.getParam("custom_ui_selector","","string");return null!==Ud.getParent(e,function(e){return Fd.isEditorUIElement(e)||!!n&&t.dom.is(e,n)})}function hd(n,e){var t=e.editor;gd(t),t.on("focusin",function(){var e=n.focusedEditor;e!==t&&(e&&e.fire("blur",{focusedEditor:t}),n.setActive(t),(n.focusedEditor=t).fire("focus",{blurredEditor:e}),t.focus(!0))}),t.on("focusout",function(){Ar.setEditorTimeout(t,function(){var e=n.focusedEditor;pd(t,function(e){try{return od(Pn(Et.fromDom(e.getElement()))).fold(function(){return document.body},function(e){return e.dom})}catch(e){return document.body}}(t))||e!==t||(t.fire("blur",{focusedEditor:null}),n.focusedEditor=null)})}),Ad||(Ad=function(e){var t=n.activeEditor;t&&!function(e){if(Bn()&&V(e.target)){var t=Et.fromDom(e.target);if(_n(t)&&V(t.dom.shadowRoot)&&e.composed&&e.composedPath){var n=e.composedPath();if(n)return Q(n)}}return ve.from(e.target)}(e).each(function(e){e.ownerDocument===document&&(e===document.body||pd(t,e)||n.focusedEditor!==t||(t.fire("blur",{focusedEditor:null}),n.focusedEditor=null))})},Ud.bind(document,"focusin",Ad))}function vd(e,t){e.focusedEditor===t.editor&&(e.focusedEditor=null),e.activeEditor||(Ud.unbind(document,"focusin",Ad),Ad=null)}function bd(t,e){var n,r;n=Et.fromDom(t.getBody()),((r=e).collapsed?ve.from(Iu(r.startContainer,r.startOffset)).map(Et.fromDom):ve.none()).bind(function(e){return bo(e)?ve.some(e):!1===Ve(n,e)?ve.some(n):ve.none()}).bind(function(e){return rf(e.dom)}).fold(function(){t.selection.normalize()},function(e){return t.selection.setRng(e.toRange())})}function yd(t){if(t.setActive)try{t.setActive()}catch(e){t.focus()}else t.focus()}function Cd(e){return e.inline?(r=e.getBody())&&(rd(t=Et.fromDom(r))||od(Pn(n=t)).filter(function(e){return n.dom.contains(e.dom)}).isSome()):e.iframeElement&&rd(Et.fromDom(e.iframeElement));var t,n,r}function xd(e,t,n,r,o){var i=n?t.startContainer:t.endContainer,a=n?t.startOffset:t.endOffset;return ve.from(i).map(Et.fromDom).map(function(e){return r&&t.collapsed?e:Mt(e,o(e,a)).getOr(e)}).bind(function(e){return _n(e)?ve.some(e):Ot(e).filter(_n)}).map(function(e){return e.dom}).getOr(e)}function wd(e,t,n){return xd(e,t,!0,n,function(e,t){return Math.min(zt(e),t)})}function Sd(e,t,n){return xd(e,t,!1,n,function(e,t){return 0<t?t-1:t})}function Nd(e,t){for(var n=e;e&&Vn(e)&&0===e.length;)e=t?e.nextSibling:e.previousSibling;return e||n}function Ed(n,e){return A(e,function(e){var t=n.fire("GetSelectionRange",{range:e});return t.range!==e?t.range:e})}function kd(e,t,n){var r=n?"lastChild":"firstChild",o=n?"prev":"next";if(e[r])return e[r];if(e!==t){var i=e[o];if(i)return i;for(var a=e.parent;a&&a!==t;a=a.parent)if(i=a[o])return i}}function _d(e){var t="a"===e.name&&!e.attr("href")&&e.attr("id");return e.attr("name")||e.attr("id")&&!e.firstChild||e.attr("data-mce-bookmark")||t}var Ad,Rd=function(r,e){return r.view(e).fold(J([]),function(e){var t=r.owner(e),n=Rd(r,t);return[e].concat(n)})},Dd=Object.freeze({__proto__:null,view:function(e){var t;return(e.dom===document?ve.none():ve.from(null===(t=e.dom.defaultView)||void 0===t?void 0:t.frameElement)).map(Et.fromDom)},owner:Dt}),Td=function(e,t,n,r){var o=Et.fromDom(e.getBody()),i=Et.fromDom(e.getDoc());o.dom.offsetWidth;var a,u,s,c,l=(a=Et.fromDom(n.startContainer),u=n.startOffset,s=function(e,t){var n=Tn(e);if(0===n.length||Vf(e))return{element:e,offset:t};if(t<n.length&&!Vf(n[t]))return{element:n[t],offset:0};var r=n[n.length-1];return Vf(r)?{element:e,offset:t}:"img"===kt(r)?{element:r,offset:1}:An(r)?{element:r,offset:Ml(r).length}:{element:r,offset:Tn(r).length}}(a,u),c=Et.fromHtml('<span data-mce-bogus="all" style="display: inline-block;">\ufeff</span>'),qt(s.element,c),qf(c,function(){return In(c)}));Wf(e,i,t,l,r),l.cleanup()},Od=function(e,t,n){var r=n.startContainer,o=n.startOffset,i=n.endContainer,a=n.endOffset;t(Et.fromDom(r),Et.fromDom(i));var u=e.dom.createRng();u.setStart(r,o),u.setEnd(i,a),e.selection.setRng(n)},Bd=ir([{before:["element"]},{on:["element","offset"]},{after:["element"]}]),Pd=(Bd.before,Bd.on,Bd.after,function(e){return e.fold(u,u,u)}),Ld=ir([{domRange:["rng"]},{relative:["startSitu","finishSitu"]},{exact:["start","soffset","finish","foffset"]}]),Id={domRange:Ld.domRange,relative:Ld.relative,exact:Ld.exact,exactFromRange:function(e){return Ld.exact(e.start,e.soffset,e.finish,e.foffset)},getWin:function(e){return Tt(e.match({domRange:function(e){return Et.fromDom(e.startContainer)},relative:function(e,t){return Pd(e)},exact:function(e,t,n,r){return e}}))},range:function(e,t,n,r){return{start:e,soffset:t,finish:n,foffset:r}}},Md=dt().browser,Fd={isEditorUIElement:function(e){var t=e.className.toString();return-1!==t.indexOf("tox-")||-1!==t.indexOf("mce-")}},Ud=eu.DOM,zd=function(e){return e.editorManager.setActive(e)},Hd={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11},jd=(Vd.create=function(e,t){var n=new Vd(e,Hd[e]||1);return t&&ne(t,function(e,t){n.attr(t,e)}),n},Vd.prototype.replace=function(e){return e.parent&&e.remove(),this.insert(e,this),this.remove(),this},Vd.prototype.attr=function(e,t){var n,r=this;if("string"!=typeof e)return null!=e&&ne(e,function(e,t){r.attr(t,e)}),r;if(n=r.attributes){if(void 0===t)return n.map[e];if(null===t){if(e in n.map){delete n.map[e];for(var o=n.length;o--;)if(n[o].name===e)return n.splice(o,1),r}return r}if(e in n.map){for(o=n.length;o--;)if(n[o].name===e){n[o].value=t;break}}else n.push({name:e,value:t});return n.map[e]=t,r}},Vd.prototype.clone=function(){var e,t=new Vd(this.name,this.type);if(e=this.attributes){var n=[];n.map={};for(var r=0,o=e.length;r<o;r++){var i=e[r];"id"!==i.name&&(n[n.length]={name:i.name,value:i.value},n.map[i.name]=i.value)}t.attributes=n}return t.value=this.value,t.shortEnded=this.shortEnded,t},Vd.prototype.wrap=function(e){return this.parent.insert(e,this),e.append(this),this},Vd.prototype.unwrap=function(){for(var e=this.firstChild;e;){var t=e.next;this.insert(e,this,!0),e=t}this.remove()},Vd.prototype.remove=function(){var e=this.parent,t=this.next,n=this.prev;return e&&(e.firstChild===this?(e.firstChild=t)&&(t.prev=null):n.next=t,e.lastChild===this?(e.lastChild=n)&&(n.next=null):t.prev=n,this.parent=this.next=this.prev=null),this},Vd.prototype.append=function(e){e.parent&&e.remove();var t=this.lastChild;return t?((t.next=e).prev=t,this.lastChild=e):this.lastChild=this.firstChild=e,e.parent=this,e},Vd.prototype.insert=function(e,t,n){e.parent&&e.remove();var r=t.parent||this;return n?(t===r.firstChild?r.firstChild=e:t.prev.next=e,e.prev=t.prev,(e.next=t).prev=e):(t===r.lastChild?r.lastChild=e:t.next.prev=e,e.next=t.next,(e.prev=t).next=e),e.parent=r,e},Vd.prototype.getAll=function(e){for(var t=[],n=this.firstChild;n;n=kd(n,this))n.name===e&&t.push(n);return t},Vd.prototype.children=function(){for(var e=[],t=this.firstChild;t;t=t.next)e.push(t);return e},Vd.prototype.empty=function(){if(this.firstChild){for(var e=[],t=this.firstChild;t;t=kd(t,this))e.push(t);for(var n=e.length;n--;)(t=e[n]).parent=t.firstChild=t.lastChild=t.next=t.prev=null}return this.firstChild=this.lastChild=null,this},Vd.prototype.isEmpty=function(e,t,n){void 0===t&&(t={});var r=this.firstChild;if(_d(this))return!1;if(r)do{if(1===r.type){if(r.attr("data-mce-bogus"))continue;if(e[r.name])return!1;if(_d(r))return!1}if(8===r.type)return!1;if(3===r.type&&!function(e){if($r(e.value)){var t=e.parent;return!t||"span"===t.name&&!t.attr("style")||!/^[ ]+$/.test(e.value)}}(r))return!1;if(3===r.type&&r.parent&&t[r.parent.name]&&$r(r.value))return!1;if(n&&n(r))return!1}while(r=kd(r,this));return!0},Vd.prototype.walk=function(e){return kd(this,null,e)},Vd);function Vd(e,t){this.name=e,1===(this.type=t)&&(this.attributes=[],this.attributes.map={})}function qd(e){return X(e.nodeValue)&&Te(e.nodeValue,So)}function $d(e){return(0===e.length?"":A(e,function(e){return"["+e+"]"}).join(",")+",")+'[data-mce-bogus="all"]'}function Wd(e,t,n){return document.createTreeWalker(e,t,n,!1)}function Kd(e){return Wd(e,NodeFilter.SHOW_COMMENT,function(e){return qd(e)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP})}function Xd(e){return Wd(e,NodeFilter.SHOW_TEXT,function(e){if(qd(e)){var t=e.parentNode;return t&&Ee(om,t.nodeName)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}return NodeFilter.FILTER_SKIP})}function Yd(e){return null!==Kd(e).nextNode()}function Gd(e){return null!==Xd(e).nextNode()}function Jd(e,t){return null!==t.querySelector($d(e))}function Qd(n,e){Y(e.querySelectorAll($d(n)),function(e){var t=Et.fromDom(e);"all"===vn(t,"data-mce-bogus")?In(t):Y(n,function(e){yn(t,e)&&Cn(t,e)})})}function Zd(e){for(var t=e.nextNode();null!==t;)t.nodeValue=null,t=e.nextNode()}function em(r,e){var t=[{condition:R(Jd,e),action:R(Qd,e)},{condition:Yd,action:im},{condition:Gd,action:am}],o=r,i=!1;return Y(t,function(e){var t=e.condition,n=e.action;t(o)&&(i||(o=r.cloneNode(!0),i=!0),n(o))}),o}function tm(o){return{compare:function(e,t){return e.nodeName===t.nodeName&&!(!r(n(e),n(t))||!r(o.parseStyle(o.getAttrib(e,"style")),o.parseStyle(o.getAttrib(t,"style")))||Qc(e)||Qc(t));function n(n){var r={};return um(o.getAttribs(n),function(e){var t=e.nodeName.toLowerCase();0!==t.indexOf("_")&&"style"!==t&&0!==t.indexOf("data-")&&(r[t]=o.getAttrib(n,t))}),r}function r(e,t){var n,r;for(r in e)if(Ee(e,r)){if(void 0===(n=t[r]))return;if(e[r]!==n)return;delete t[r]}for(r in t)if(Ee(t,r))return;return 1}}}}function nm(e){var u=[],s=(e=e||{}).indent,c=sm(e.indent_before||""),l=sm(e.indent_after||""),f=Zo.getEncodeFunc(e.entity_encoding||"raw",e.entities),d="html"===e.element_format;return{start:function(e,t,n){var r,o,i,a;if(s&&c[e]&&0<u.length&&0<(a=u[u.length-1]).length&&"\n"!==a&&u.push("\n"),u.push("<",e),t)for(r=0,o=t.length;r<o;r++)i=t[r],u.push(" ",i.name,'="',f(i.value,!0),'"');u[u.length]=!n||d?">":" />",n&&s&&l[e]&&0<u.length&&0<(a=u[u.length-1]).length&&"\n"!==a&&u.push("\n")},end:function(e){var t;u.push("</",e,">"),s&&l[e]&&0<u.length&&0<(t=u[u.length-1]).length&&"\n"!==t&&u.push("\n")},text:function(e,t){0<e.length&&(u[u.length]=t?e:f(e))},cdata:function(e){u.push("<![CDATA[",e,"]]>")},comment:function(e){u.push("\x3c!--",e,"--\x3e")},pi:function(e,t){t?u.push("<?",e," ",f(t),"?>"):u.push("<?",e,"?>"),s&&u.push("\n")},doctype:function(e){u.push("<!DOCTYPE",e,">",s?"\n":"")},reset:function(){u.length=0},getContent:function(){return u.join("").replace(/\n$/,"")}}}function rm(t,g){void 0===g&&(g=oo());var p=nm(t);return(t=t||{}).validate=!("validate"in t)||t.validate,{serialize:function(e){var f=t.validate,d={3:function(e){p.text(e.value,e.raw)},8:function(e){p.comment(e.value)},7:function(e){p.pi(e.name,e.value)},10:function(e){p.doctype(e.value)},4:function(e){p.cdata(e.value)},11:function(e){if(e=e.firstChild)for(;m(e),e=e.next;);}};p.reset();var m=function(e){var t=d[e.type];if(t)t(e);else{var n=e.name,r=e.shortEnded,o=e.attributes;if(f&&o&&1<o.length){var i=[];i.map={};var a=g.getElementRule(e.name);if(a){for(var u=0,s=a.attributesOrder.length;u<s;u++)(c=a.attributesOrder[u])in o.map&&(l=o.map[c],i.map[c]=l,i.push({name:c,value:l}));for(var c,l,u=0,s=o.length;u<s;u++)(c=o[u].name)in i.map||(l=o.map[c],i.map[c]=l,i.push({name:c,value:l}));o=i}}if(p.start(e.name,o,r),!r){if(e=e.firstChild)for(;m(e),e=e.next;);p.end(n)}}};return 1!==e.type||t.inner?d[11](e):m(e),p.getContent()}}}var om=Nt.makeMap("NOSCRIPT STYLE SCRIPT XMP IFRAME NOEMBED NOFRAMES PLAINTEXT"," "),im=i(Zd,Kd),am=i(Zd,Xd),um=Nt.each,sm=Nt.makeMap,cm=new Set;function lm(e,t){return we(e.parseStyle(e.getAttrib(t,"style")))}function fm(n,r,o){return ve.from(o.container()).filter(Vn).exists(function(e){var t=n?0:-1;return r(e.data.charAt(o.offset()+t))})}function dm(e){var t=e.container();return Vn(t)&&(0===t.data.length||No(t.data)&&Hl.isBookmarkNode(t.parentNode))}function mm(t,n){return function(e){return ve.from(Zs(t?0:-1,e)).filter(n).isSome()}}function gm(e){return Xn(e)&&"block"===wn(Et.fromDom(e),"display")}function pm(e){return Gn(e)&&!(Hn(t=e)&&"all"===t.getAttribute("data-mce-bogus"));var t}function hm(e){Xt(e),Ln(e,Et.fromHtml('<br data-mce-bogus="1">'))}function vm(n){Ut(n).each(function(t){Bt(t).each(function(e){go(n)&&Pr(t)&&go(e)&&In(t)})})}function bm(e,t){return o=D,Ve(r=t,n=e)?function(e,t){for(var n=y(t)?t:D,r=e.dom,o=[];null!==r.parentNode&&void 0!==r.parentNode;){var i=r.parentNode,a=Et.fromDom(i);if(o.push(a),!0===n(a))break;r=i}return o}(n,function(e){return o(e)||je(e,r)}).slice(0,-1):[];var n,r,o}function ym(e,t){return[e].concat(bm(e,t))}function Cm(e,t,n){return ef(e,t,n,dm)}function xm(e,t){return M(ym(Et.fromDom(t.container()),e),go)}function wm(e,n,r){return Cm(e,n.dom,r).forall(function(t){return xm(n,r).fold(function(){return!1===Qs(t,r,n.dom)},function(e){return!1===Qs(t,r,n.dom)&&Ve(e,Et.fromDom(t.container()))})})}function Sm(t,n,r){return xm(n,r).fold(function(){return Cm(t,n.dom,r).forall(function(e){return!1===Qs(e,r,n.dom)})},function(e){return Cm(t,e.dom,r).isNone()})}function Nm(e){return ic(e).exists(Pr)}function Em(e,t,n){var r=Q(U(ym(Et.fromDom(n.container()),t),go)).getOr(t);return Zl(e,r.dom,n).filter(Nm)}function km(e,t){return ic(t).exists(Pr)||Em(!0,e,t).isSome()}function _m(e,t){return ve.from(t.getNode(!0)).map(Et.fromDom).exists(Pr)||Em(!1,e,t).isSome()}function Am(e){return cs.isTextPosition(e)&&!e.isAtStart()&&!e.isAtEnd()}function Rm(e,t){return Q(U(ym(Et.fromDom(t.container()),e),go)).getOr(e)}function Dm(e,t){return Am(t)?Gg(t):Gg(t)||nf(Rm(e,t).dom,t).exists(Gg)}function Tm(e,t){return Am(t)?Yg(t):Yg(t)||tf(Rm(e,t).dom,t).exists(Yg)}function Om(e){return ic(e).bind(function(e){return hr(e,_n)}).exists(function(e){return T(["pre","pre-wrap"],wn(e,"white-space"))})}function Bm(e,t){return!Om(t)&&(ip(e,t)||up(e,t)||_m(e,t)||Dm(e,t))}function Pm(e,t){return!Om(t)&&(ap(e,t)||sp(e,t)||km(e,t)||Tm(e,t))}function Lm(e,t){return Bm(e,t)||Pm(e,(r=(n=t).container(),o=n.offset(),Vn(r)&&o<r.data.length?cs(r,o+1):n));var n,r,o}function Im(e,t){return sf(e.charAt(t))}function Mm(e){var t=e.container();return Vn(t)&&Te(t.data,wo)}function Fm(g,e){return ve.some(e).filter(Mm).bind(function(e){var t,n,r,o,i,a,u,s,c,l=e.container(),f=g,d=(i=l).data,m=cs(i,0);return(!Im(d,0)||Lm(f,m)?(s=(a=l).data,(c=A(u=s.split(""),function(e,t){return sf(e)&&0<t&&t<u.length-1&&el(u[t-1])&&el(u[t+1])?" ":e}).join(""))!==s&&(a.data=c,1)):(i.data=" "+d.slice(1),1))||(t=g,r=(n=l).data,o=cs(n,r.length-1),Im(r,r.length-1)&&!Lm(t,o)&&(n.data=r.slice(0,-1)+" ",1))?ve.some(e):ve.none()})}function Um(t){var e=Et.fromDom(t.getBody());t.selection.isCollapsed()&&Fm(e,cs.fromRangeStart(t.selection.getRng())).each(function(e){t.selection.setRng(e.toRange())})}function zm(e,t,n){var r,o,i,a,u,s,c,l;0!==n&&(o=pr(r=Et.fromDom(e),go).getOr(r),i=e.data.slice(t,t+n),a=t+n>=e.data.length&&Pm(o,cs(e,e.data.length)),u=0===t&&Bm(o,cs(e,0)),e.replaceData(t,n,(c=u,l=a,L(s=i,function(e,t){return Zc(t)||sf(t)?e.previousCharIsSpace||""===e.str&&c||e.str.length===s.length-1&&l?{previousCharIsSpace:!1,str:e.str+wo}:{previousCharIsSpace:!0,str:e.str+" "}:{previousCharIsSpace:!1,str:e.str+t}},{previousCharIsSpace:!1,str:""}).str)))}function Hm(e,t){var n=e.data.slice(t);zm(e,t,n.length-Qe(n).length)}function jm(e,t){var n=e.data.slice(0,t),r=n.length-Ze(n).length;zm(e,t-r,r)}function Vm(e,t,n,r){void 0===r&&(r=!0);var o=Ze(e.data).length,i=r?e:t,a=r?t:e;return r?i.appendData(a.data):i.insertData(0,a.data),In(Et.fromDom(a)),n&&Hm(i,o),i}function qm(e,t){return r=e,o=(n=t).container(),i=n.offset(),!1===cs.isTextPosition(n)&&o===r.parentNode&&i>cs.before(r).offset()?cs(t.container(),t.offset()-1):t;var n,r,o,i}function $m(e){return Vr(e.previousSibling)?ve.some((t=e.previousSibling,Vn(t)?cs(t,t.data.length):cs.after(t))):e.previousSibling?of(e.previousSibling):ve.none();var t}function Wm(e){return Vr(e.nextSibling)?ve.some((t=e.nextSibling,Vn(t)?cs(t,0):cs.before(t))):e.nextSibling?rf(e.nextSibling):ve.none();var t}function Km(r,o){return $m(o).orThunk(function(){return Wm(o)}).orThunk(function(){return e=r,n=cs.before((t=o).previousSibling||t.parentNode),nf(e,n).fold(function(){return tf(e,cs.after(t))},ve.some);var e,t,n})}function Xm(n,r){return Wm(r).orThunk(function(){return $m(r)}).orThunk(function(){return tf(e=n,cs.after(t=r)).fold(function(){return nf(e,cs.before(t))},ve.some);var e,t})}function Ym(t,n,e){e.fold(function(){t.focus()},function(e){t.selection.setRng(e.toRange(),n)})}function Gm(e,t){return t&&Ee(e.schema.getBlockElements(),kt(t))}function Jm(e){if(Kr(e)){var t=Et.fromHtml('<br data-mce-bogus="1">');return Xt(e),Ln(e,t),ve.some(cs.before(t.dom))}return ve.none()}function Qm(t,n,e,r){void 0===r&&(r=!0);var o,i,a,u,s,c,l,f,d,m,g,p,h,v,b=(p=n,h=t.getBody(),v=e.dom,(p?Xm:Km)(h,v).map(R(qm,v))),y=pr(e,R(Gm,t),(o=t.getBody(),function(e){return e.dom===o})),C=(u=b,i=a=e,s=Ee(t.schema.getTextInlineElements(),kt(i)),m=Bt(a).filter(An),g=Pt(a).filter(An),In(a),l=g,f=u,d=function(e,t,n){var r=e.dom,o=t.dom,i=r.data.length;return Vm(r,o,s),n.container()===o?cs(r,i):n},((c=m).isSome()&&l.isSome()&&f.isSome()?ve.some(d(c.getOrDie(),l.getOrDie(),f.getOrDie())):ve.none()).orThunk(function(){return s&&(m.each(function(e){return jm(e.dom,e.dom.length)}),g.each(function(e){return Hm(e.dom,0)})),u}));t.dom.isEmpty(t.getBody())?(t.setContent(""),t.selection.setCursorLocation()):y.bind(Jm).fold(function(){r&&Ym(t,n,C)},function(e){r&&Ym(t,n,ve.some(e))})}function Zm(e){return yu(e,"td,th")}function eg(e,t){return{start:e,end:t}}function tg(e,t){return yr(Et.fromDom(e),"td,th",t)}function ng(e){return!je(e.start,e.end)}function rg(e,n){return Tl(e.start,n).bind(function(t){return Tl(e.end,n).bind(function(e){return je(t,e)?ve.some(t):ve.none()})})}function og(e){return function(t){return rg(t,e).map(function(e){return{rng:t,table:e,cells:Zm(e)}})}}function ig(e,t,n,r){if(n.collapsed||!e.forall(ng))return ve.none();if(t.isSameTable){var o=e.bind(og(r));return ve.some({start:o,end:o})}var i,a,u=tg(n.startContainer,r),s=tg(n.endContainer,r),c=u.bind((a=r,function(t){return Tl(t,a).bind(function(e){return Z(Zm(e)).map(function(e){return eg(t,e)})})})).bind(og(r)),l=s.bind((i=r,function(t){return Tl(t,i).bind(function(e){return Q(Zm(e)).map(function(e){return eg(e,t)})})})).bind(og(r));return ve.some({start:c,end:l})}function ag(e,t){return z(e,function(e){return je(e,t)})}function ug(n){return dn(ag(n.cells,n.rng.start),ag(n.cells,n.rng.end),function(e,t){return n.cells.slice(e,t+1)})}function sg(e,t){var n=t.startTable,r=t.endTable,o=e.cloneRange();return n.each(function(e){return o.setStartAfter(e.dom)}),r.each(function(e){return o.setEndBefore(e.dom)}),o}function cg(e,t){var n,r,o,i,a,u,s,c,l,f,d,m,g,p,h,v,b=(n=e,function(e){return je(n,e)}),y=dn(tg((r=t).startContainer,o=b),tg(r.endContainer,o),eg),C=(l=b,f=x((c=t).startContainer),d=x(c.endContainer),m=f.isSome(),g=d.isSome(),p=dn(f,d,je).getOr(!1),{startTable:f,endTable:d,isStartInTable:m,isEndInTable:g,isSameTable:p,isMultiTable:!p&&m&&g});function x(e){return Tl(Et.fromDom(e),l)}return h=t,v=b,y.exists(function(e){return!ng(t=e)&&rg(t,v).exists(function(e){var t=e.dom.rows;return 1===t.length&&1===t[0].cells.length})&&Ol(e.start,h);var t})?y.map(function(e){return fp.singleCellTable(t,e.start)}):C.isMultiTable?ig(y,u=C,s=t,b).bind(function(e){var t=e.start,n=e.end,r=t.bind(ug).getOr([]),o=n.bind(ug).getOr([]);if(0<r.length&&0<o.length){var i=sg(s,u);return ve.some(fp.multiTable(r,o,i))}return ve.none()}):ig(y,i=C,a=t,b).bind(function(e){var t=e.start,n=e.end;return t.or(n)}).bind(function(e){var t=i.isSameTable,n=ug(e).getOr([]);if(t&&e.cells.length===n.length)return ve.some(fp.fullTable(e.table));if(0<n.length){if(t)return ve.some(fp.partialTable(n,ve.none()));var r=sg(a,i);return ve.some(fp.partialTable(n,ve.some(_e(_e({},i),{rng:r}))))}return ve.none()})}function lg(e){return Y(e,function(e){Cn(e,"contenteditable"),hm(e)}),0}function fg(e,t,n,r){var o=n.cloneRange();r?(o.setStart(n.startContainer,n.startOffset),o.setEndAfter(t.dom.lastChild)):(o.setStartBefore(t.dom.firstChild),o.setEnd(n.endContainer,n.endOffset)),mp(e,o,t,!1)}function dg(e){var t=Dl(e),n=Et.fromDom(e.selection.getNode());Jn(n.dom)&&Kr(n)?e.selection.setCursorLocation(n.dom,0):e.selection.collapse(!0),1<t.length&&F(t,function(e){return je(e,n)})&&pn(n,"data-mce-selected","1")}function mg(s,c,e){var l=s.selection.getRng();return lg(e.bind(function(e){var t,n,r,o=e.rng,i=e.isStartInTable,a=(t=i?o.endContainer:o.startContainer,ve.from(s.dom.getParent(t,s.dom.isBlock)).map(Et.fromDom));o.deleteContents(),n=s,r=i,a.filter(Kr).each(function(e){r?In(e):(hm(e),n.selection.setCursorLocation(e.dom,0))});var u=i?c[0]:c[c.length-1];return fg(s,u,l,i),Kr(u)?ve.none():ve.some(i?c.slice(1):c.slice(0,-1))}).getOr(c)),dg(s),!0}function gg(e,t,n,r){var o=e.selection.getRng(),i=t[0],a=n[n.length-1];fg(e,i,o,!0),fg(e,a,o,!1);var u=Kr(i)?t:t.slice(1),s=Kr(a)?n:n.slice(0,-1);return lg(u.concat(s)),r.deleteContents(),dg(e),!0}function pg(e,t){return Qm(e,!1,t),!0}function hg(e,t){return M(ym(t,e),yo)}function vg(e,t){return(e?tp:np)(t)}function bg(f,d,s){var m=Et.fromDom(f.getBody());return gp(m,s).fold(function(){return o=f,i=d,a=m,e=s,u=cs.fromRangeStart(o.selection.getRng()),hg(a,e).bind(function(e){return Kr(e)?pp(o,e):(t=a,n=e,r=u,Hc(i,o.getBody(),r).bind(function(e){return hg(t,Et.fromDom(e.getNode())).map(function(e){return!1===je(e,n)})}));var t,n,r}).getOr(!1)||(n=d,r=cs.fromRangeStart((t=f).selection.getRng()),vg(n,r)||Zl(n,t.getBody(),r).exists(function(e){return vg(n,e)}));var o,i,a,e,u,t,n,r},function(e){return n=d,r=m,o=e,i=cs.fromRangeStart((t=f).selection.getRng()),(Kr(o)?pp(t,o):(u=r,c=o,l=i,Hc(s=n,(a=t).getBody(),l).bind(function(e){return r=s,o=l,i=e,rf((n=c).dom).bind(function(t){return of(n.dom).map(function(e){return r?o.isEqual(t)&&i.isEqual(e):o.isEqual(e)&&i.isEqual(t)})}).getOr(!0)?pp(a,c):(t=c,gp(u,Et.fromDom(e.getNode())).map(function(e){return!1===je(e,t)}));var t,n,r,o,i}).or(ve.some(!0)))).getOr(!1);var a,u,s,c,l,t,n,r,o,i})}function yg(e,t){var n,r,o,i,a,u,s,c,l=Et.fromDom(e.selection.getStart(!0)),f=Dl(e);return e.selection.isCollapsed()&&0===f.length?bg(e,t,l):(r=l,o=f,i=Et.fromDom((n=e).getBody()),a=n.selection.getRng(),0!==o.length?mg(n,o,ve.none()):(u=n,c=a,gp(s=i,r).fold(function(){return t=u,cg(s,c).map(function(e){return e.fold(R(mp,t),R(pg,t),R(mg,t),R(gg,t))});var t},function(e){return pp(u,e)}).getOr(!1)))}function Cg(e){return e.collapsed?e:(a=e,u=cs.fromRangeStart(a),s=cs.fromRangeEnd(a),c=a.commonAncestorContainer,Zl(!1,c,s).map(function(e){return!Qs(u,s,c)&&Qs(u,e,c)?(t=u.container(),n=u.offset(),r=e.container(),o=e.offset(),(i=document.createRange()).setStart(t,n),i.setEnd(r,o),i):a;var t,n,r,o,i}).getOr(a));var a,u,s,c}function xg(e,t){var n,r,o,i,a,u=t.firstChild,s=t.lastChild;return u&&"meta"===u.name&&(u=u.next),r=s=s&&"mce_marker"===s.attr("id")?s.prev:s,o=(n=e).getNonEmptyElements(),r&&(r.isEmpty(o)||(i=r,n.getBlockElements()[i.name]&&i.firstChild&&i.firstChild===i.lastChild&&("br"===(a=i.firstChild).name||a.value===wo)))&&(s=s.prev),u&&u===s&&("ul"===u.name||"ol"===u.name)}function wg(e){return 0<e.length&&(!(r=e[e.length-1]).firstChild||(t=r)&&t.firstChild&&t.firstChild===t.lastChild&&((n=t.firstChild).data===wo||Kn(n)))?e.slice(0,-1):e;var t,n,r}function Sg(e,t){var n=e.getParent(t,e.isBlock);return n&&"LI"===n.nodeName?n:null}function Ng(e,t){var n=cs.after(e),r=Mc(t).prev(n);return r?r.toRange():null}function Eg(e,o,i,t){function n(e){var t=cs.fromRangeStart(i),n=Mc(o.getRoot()),r=1===e?n.prev(t):n.next(t);return!r||Sg(o,r.getNode())!==R}var r,a,u,s,c,l,f,d,m,g,p,h,v,b,y,C,x,w,S,N,E,k,_,A=(r=o,c=e.serialize(t),u=(a=r.createFragment(c)).firstChild,s=a.lastChild,u&&"META"===u.nodeName&&u.parentNode.removeChild(u),s&&"mce_marker"===s.id&&s.parentNode.removeChild(s),a),R=Sg(o,i.startContainer),D=wg(U(A.firstChild.childNodes,function(e){return"LI"===e.nodeName})),T=o.getRoot();return n(1)?(S=T,_=(w=R).parentNode,Nt.each(D,function(e){_.insertBefore(e,w)}),N=S,E=cs.before(w),(k=Mc(N).next(E))?k.toRange():null):n(2)?(l=R,d=T,o.insertAfter((f=D).reverse(),l),Ng(f[0],d)):(g=D,p=T,h=m=R,b=(v=i).cloneRange(),y=v.cloneRange(),b.setStartBefore(h),y.setEndAfter(h),C=[b.cloneContents(),y.cloneContents()],(x=m.parentNode).insertBefore(C[0],m),Nt.each(g,function(e){x.insertBefore(e,m)}),x.insertBefore(C[1],m),x.removeChild(m),Ng(g[g.length-1],p))}function kg(e,t,n){var r,o,i,a,u=e.selection,s=e.dom;/^ | $/.test(t)&&(r=s,o=u.getRng(),i=t,i=Bm(a=Et.fromDom(r.getRoot()),cs.fromRangeStart(o))?i.replace(/^ /," "):i.replace(/^ /," "),t=i=Pm(a,cs.fromRangeEnd(o))?i.replace(/( | )(<br( \/)>)?$/," "):i.replace(/ (<br( \/)?>)?$/," "));var c=e.parser,l=n.merge,f=rm({validate:e.getParam("validate")},e.schema),d='<span id="mce_marker" data-mce-type="bookmark"></span>',m=e.fire("BeforeSetContent",{content:t,format:"html",selection:!0,paste:n.paste});if(m.isDefaultPrevented())e.fire("SetContent",{content:m.content,format:"html",selection:!0,paste:n.paste});else{t=m.content,-1===(t=n.preserve_zwsp?t:Eo(t)).indexOf("{$caret}")&&(t+="{$caret}"),t=t.replace(/\{\$caret\}/,d);var g,p,h=(g=u.getRng()).startContainer||(g.parentElement?g.parentElement():null),v=e.getBody();h===v&&u.isCollapsed()&&s.isBlock(v.firstChild)&&((p=v.firstChild)&&!e.schema.getShortEndedElements()[p.nodeName])&&s.isEmpty(v.firstChild)&&((g=s.createRng()).setStart(v.firstChild,0),g.setEnd(v.firstChild,0),u.setRng(g)),u.isCollapsed()||function(e){var t=e.dom,n=Cg(e.selection.getRng());e.selection.setRng(n);var r,o=t.getParent(n.startContainer,hp),i=n;null!==(r=o)&&r===t.getParent(i.endContainer,hp)&&Ol(Et.fromDom(r),i)?mp(e,n,Et.fromDom(o)):e.getDoc().execCommand("Delete",!1,null)}(e);var b,y,C,x,w,S,N,E,k,_,A,R,D,T,O={context:(I=u.getNode()).nodeName.toLowerCase(),data:n.data,insert:!0},B=c.parse(t,O);if(!0===n.paste&&xg(e.schema,B)&&Sg(s,I))return g=Eg(f,s,u.getRng(),B),u.setRng(g),void e.fire("SetContent",m);if(function(){for(var e=B;e=e.walk();)1===e.type&&e.attr("data-mce-fragment","1")}(),"mce_marker"===(L=B.lastChild).attr("id"))for(var P=L,L=L.prev;L;L=L.walk(!0))if(3===L.type||!s.isBlock(L.name)){e.schema.isValidChild(L.parent.name,"span")&&L.parent.insert(P,L,"br"===L.name);break}if(e._selectionOverrides.showBlockCaretContainer(I),O.invalid){e.selection.setContent(d);var I=u.getNode(),M=e.getBody();for(9===I.nodeType?I=L=M:L=I;L!==M;)L=(I=L).parentNode;t=I===M?M.innerHTML:s.getOuterHTML(I),t=f.serialize(c.parse(t.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i,function(){return f.serialize(B)}))),I===M?s.setHTML(M,t):s.setOuterHTML(I,t)}else b=e,y=t=f.serialize(B),"all"===(C=I).getAttribute("data-mce-bogus")?C.parentNode.insertBefore(b.dom.createFragment(y),C):(x=C.firstChild,w=C.lastChild,!x||x===w&&"BR"===x.nodeName?b.dom.setHTML(C,y):b.selection.setContent(y));N=l,_=(S=e).schema.getTextInlineElements(),A=S.dom,N&&(E=S.getBody(),k=tm(A),Nt.each(A.select("*[data-mce-fragment]"),function(e){if(V(_[e.nodeName.toLowerCase()])&&j(lm(A,e),function(e){return!cm.has(e)}))for(var t=e.parentNode;V(t)&&t!==E&&!function(r,o,i){function a(e){var t=r.getStyle(o,e),n=r.getStyle(i,e);return Be(t)&&Be(n)&&t!==n}var e=lm(r,o),u=lm(r,i);return F(e,function(t){function e(e){return F(e,function(e){return e===t})}if(e(u)||!e(Xg))return a(t);var n=U(u,function(t){return F(Xg,function(e){return Ge(t,e)})});return F(n,a)})}(A,e,t);t=t.parentNode)if(k.compare(t,e)){A.remove(e,!0);break}})),function(n,e){var t,r=n.dom,o=n.selection;if(e){o.scrollIntoView(e);var i=bf(n.getBody(),e);if("false"===r.getContentEditable(i))return r.remove(e),o.select(i);var a,u=r.createRng(),s=e.previousSibling;Vn(s)?(u.setStart(s,s.nodeValue.length),xt.ie||(a=e.nextSibling,Vn(a)&&(s.appendData(a.data),a.parentNode.removeChild(a)))):(u.setStartBefore(e),u.setEndBefore(e));var c=r.getParent(e,r.isBlock);r.remove(e),c&&r.isEmpty(c)&&(n.$(c).empty(),u.setStart(c,0),u.setEnd(c,0),hp(c)||c.getAttribute("data-mce-fragment")||!(t=function(e){var t=cs.fromRangeStart(e);if(t=Mc(n.getBody()).next(t))return t.toRange()}(u))?r.add(c,r.create("br",{"data-mce-bogus":"1"})):(u=t,r.remove(c))),o.setRng(u)}}(e,s.get("mce_marker")),R=e.getBody(),Nt.each(R.getElementsByTagName("*"),function(e){e.removeAttribute("data-mce-fragment")}),D=s,T=u.getStart(),ve.from(D.getParent(T,"td,th")).map(Et.fromDom).each(vm),e.fire("SetContent",m),e.addVisual()}}function _g(e){return e instanceof jd}function Ag(e,t,n){var r;e.dom.setHTML(e.getBody(),t),!0!==n&&Cd(r=e)&&rf(r.getBody()).each(function(e){var t=e.getNode(),n=cn(t)?rf(t).getOr(e):e;r.selection.setRng(n.toRange())})}function Rg(u,s,e){var t,n=(t=s,_e(_e({format:"html"},e),{set:!0,content:_g(t)?"":t})),c=e.no_events?n:u.fire("BeforeSetContent",n);return _g(s)||(s=c.content),ve.from(u.getBody()).fold(J(s),function(e){return _g(s)?function(e,t,n,r){var o,i,u,a;o=e.parser.getNodeFilters(),i=e.parser.getAttributeFilters(),u=n,a=function(e,n){var t,r,o={},i={},a=[];for(t in u.firstChild&&vp(u.firstChild,function(t){Y(e,function(e){e.name===t.name&&(o[e.name]?o[e.name].nodes.push(t):o[e.name]={filter:e,nodes:[t]})}),Y(n,function(e){"string"==typeof t.attr(e.name)&&(i[e.name]?i[e.name].nodes.push(t):i[e.name]={filter:e,nodes:[t]})})}),o)Ee(o,t)&&a.push(o[t]);for(r in i)Ee(i,r)&&a.push(i[r]);return a}(o,i),Y(a,function(t){Y(t.filter.callbacks,function(e){e(t.nodes,t.filter.name,{})})});var s=rm({validate:e.validate},e.schema).serialize(n);return r.content=Eo(Co(Et.fromDom(t))?s:Nt.trim(s)),Ag(e,r.content,r.no_selection),r.no_events||e.fire("SetContent",r),n}(u,e,s,c):(t=u,n=e,o=c,0===(r=Eo(r=s)).length||/^\s+$/.test(r)?(i='<br data-mce-bogus="1">',"TABLE"===n.nodeName?r="<tr><td>"+i+"</td></tr>":/^(UL|OL)$/.test(n.nodeName)&&(r="<li>"+i+"</li>"),r=(a=ks(t))&&t.schema.isValidChild(n.nodeName.toLowerCase(),a.toLowerCase())?(r=i,t.dom.createHTML(a,_s(t),r)):r||'<br data-mce-bogus="1">',Ag(t,r,o.no_selection),t.fire("SetContent",o)):("raw"!==o.format&&(r=rm({validate:t.validate},t.schema).serialize(t.parser.parse(r,{isRootContent:!0,insert:!0}))),o.content=Co(Et.fromDom(n))?r:Nt.trim(r),Ag(t,o.content,o.no_selection),o.no_events||t.fire("SetContent",o)),o.content);var t,n,r,o,i,a})}function Dg(e){return y(e)?e:D}function Tg(i,e,t){var n=e(i),a=Dg(t);return n.orThunk(function(){return a(i)?ve.none():function(e){for(var t=i.dom,n=Dg(a);t.parentNode;){var t=t.parentNode,r=Et.fromDom(t),o=e(r);if(o.isSome())return o;if(n(r))break}return ve.none()}(e)})}function Og(e,t,n){var r=e.formatter.get(n);if(r)for(var o=0;o<r.length;o++){var i=r[o];if(gl(i)&&!1===i.inherit&&e.dom.is(t,i.selector))return 1}}function Bg(t,e,n,r,o){var i=t.dom.getRoot();return e!==i&&(e=t.dom.getParent(e,function(e){return!!Og(t,e,n)||e.parentNode===i||!!yp(t,e,n,r,!0)}),!!yp(t,e,n,r,o))}function Pg(e,t,n){return!!bp(t,n.inline)||!!bp(t,n.block)||(n.selector?1===t.nodeType&&e.is(t,n.selector):void 0)}function Lg(e,t,n,r,o,i){var a=n[r];if(y(n.onmatch))return n.onmatch(t,n,r);if(a)if(b(a.length)){for(var u in a)if(Ee(a,u)){var s="attributes"===r?e.getAttrib(t,u):cl(e,t,u),c=al(a[u],i),l=K(s)||Pe(s);if(!l||!K(c)){if(o&&l&&!n.exact)return;if((!o||n.exact)&&!bp(s,sl(e,c,u)))return}}}else for(var f=0;f<a.length;f++)if("attributes"===r?e.getAttrib(t,a[f]):cl(e,t,a[f]))return 1;return 1}function Ig(e,t,n,r,o){if(r)return Bg(e,r,t,n,o);if(r=e.selection.getNode(),Bg(e,r,t,n,o))return!0;var i=e.selection.getStart();return!(i===r||!Bg(e,i,t,n,o))}function Mg(e){return 0<function(e){for(var t=[];e;){if(3===e.nodeType&&e.nodeValue!==Cp||1<e.childNodes.length)return[];1===e.nodeType&&t.push(e),e=e.firstChild}return t}(e).length}function Fg(e){if(e){var t=new Dr(e,e);for(e=t.current();e;e=t.next())if(Vn(e))return e}return null}function Ug(e){var t=Et.fromTag("span");return hn(t,{id:xp,"data-mce-bogus":"1","data-mce-type":"format-caret"}),e&&Ln(t,Et.fromText(Cp)),t}function zg(e,t,n){void 0===n&&(n=!0);var r,o,i,a,u,s,c,l,f=e.dom,d=e.selection;Mg(t)?Qm(e,!1,Et.fromDom(t),n):(r=d.getRng(),o=f.getParent(t,f.isBlock),i=r.startContainer,a=r.startOffset,u=r.endContainer,s=r.endOffset,(l=Fg(t))&&l.nodeValue.charAt(0)===Cp&&l.deleteData(0,1),c=l,f.remove(t,!0),i===c&&0<a&&r.setStart(c,a-1),u===c&&0<s&&r.setEnd(c,s-1),o&&f.isEmpty(o)&&hm(Et.fromDom(o)),d.setRng(r))}function Hg(e,t,n){void 0===n&&(n=!0);var r=e.dom,o=e.selection;if(t)zg(e,t,n);else if(!(t=qc(e.getBody(),o.getStart())))for(;t=r.get(xp);)zg(e,t,!1)}function jg(e,t){return e.appendChild(t),t}function Vg(e,t){var n=P(e,function(e,t){return jg(e,t.cloneNode(!1))},t);return jg(n,n.ownerDocument.createTextNode(Cp))}function qg(o,e,t,i,n,r){var a,u,s=o.formatter,c=o.dom,l=U(we(s.get()),function(e){return e!==i&&!Te(e,"removeformat")});if(0<U((a=o,u=t,L(l,function(e,t){var n=dl(a,t);return a.formatter.matchNode(u,t,{},n)?e.concat([t]):e},[])),function(e){return n=i,r=["inline","block","selector","attributes","styles","classes"],!F((t=o).formatter.get(e),function(e){var i=a(e);return F(t.formatter.get(n),function(e){var t,n=a(e),r=i,o=n;return d(t=void 0===t?p:t).eq(r,o)})});function a(e){return ae(e,function(e,t){return F(r,function(e){return e===t})})}var t,n,r}).length){var f=t.cloneNode(!1);return c.add(e,f),s.remove(i,n,f,r),c.remove(f),ve.some(f)}return ve.none()}function $g(e,t,n,r){var o,i,a,u,s,c,l,f,d,m,g,p,h,v,b,y=e.dom,C=e.selection,x=[],w=C.getRng(),S=w.startContainer,N=w.startOffset,E=S;for(3===S.nodeType&&(N!==S.nodeValue.length&&(o=!0),E=E.parentNode);E;){if(yp(e,E,t,n,r)){i=E;break}E.nextSibling&&(o=!0),x.push(E),E=E.parentNode}i&&(o?(a=C.getBookmark(),w.collapse(!0),u=Pf(kl(e,w,e.formatter.get(t),!0)),e.formatter.remove(t,n,u,r),C.moveToBookmark(a)):(s=qc(e.getBody(),i),d=c=Ug(!1).dom,(p=(g=e.dom).getParent(m=null!==s?s:i,R(ol,e)))&&g.isEmpty(p)?m.parentNode.replaceChild(d,m):(h=Et.fromDom(m),v=yu(h,"br"),b=U(function(){for(var e=[],t=h.dom;t;)e.push(Et.fromDom(t)),t=t.lastChild;return e}().slice(-1),Pr),v.length===b.length&&Y(b,In),g.isEmpty(m)?m.parentNode.replaceChild(d,m):g.insertAfter(d,m)),l=qg(e,c,i,t,n,r),f=Vg(x.concat(l.toArray()),c),zg(e,s,!1),C.setCursorLocation(f,1),y.isEmpty(i)&&y.remove(i)))}function Wg(e,t){var n=e.schema.getTextInlineElements();return Ee(n,kt(t))&&!Vc(t.dom)&&!sn(t.dom)}Y(["margin","margin-left","margin-right","margin-top","margin-bottom","padding","padding-left","padding-right","padding-top","padding-bottom","border","border-width","border-style","border-color","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","float","position","left","right","top","bottom","z-index","display","transform","width","max-width","min-width","height","max-height","min-height","overflow","overflow-x","overflow-y","text-overflow","vertical-align","transition","transition-delay","transition-duration","transition-property","transition-timing-function"],function(e){cm.add(e)});var Kg,Xg=["font","text-decoration","text-emphasis"],Yg=R(fm,!0,Zc),Gg=R(fm,!1,Zc),Jg=mm(!0,gm),Qg=mm(!1,gm),Zg=mm(!0,Qn),ep=mm(!1,Qn),tp=mm(!0,cn),np=mm(!1,cn),rp=mm(!0,pm),op=mm(!1,pm),ip=R(Sm,!1),ap=R(Sm,!0),up=R(wm,!1),sp=R(wm,!0),cp=R(Em,!1),lp=R(Em,!0),fp=ir([{singleCellTable:["rng","cell"]},{fullTable:["table"]},{partialTable:["cells","outsideDetails"]},{multiTable:["startTableCells","endTableCells","betweenRng"]}]),dp=function(e){var t;return(8===_t(t=e)||"#comment"===kt(t)?Bt:Ut)(e).bind(dp).orThunk(function(){return ve.some(e)})},mp=function(e,t,n,r){void 0===r&&(r=!0),t.deleteContents();var o,i=dp(n).getOr(n),a=Et.fromDom(e.dom.getParent(i.dom,e.dom.isBlock));return Kr(a)&&(hm(a),r&&e.selection.setCursorLocation(a.dom,0)),je(n,a)||Y((fn(Ot(a),n)?[]:Ot(o=a).map(Tn).map(function(e){return U(e,function(e){return!je(o,e)})}).getOr([])).concat(Tn(n)),function(e){je(e,a)||Ve(e,a)||!Kr(e)||In(e)}),!0},gp=function(e,t){return M(ym(t,e),function(e){return _n(e)&&"caption"===kt(e)})},pp=function(e,t){return hm(t),e.selection.setCursorLocation(t.dom,0),ve.some(!0)},hp=Jn,vp=function(e,t){t(e),e.firstChild&&vp(e.firstChild,t),e.next&&vp(e.next,t)},bp=ul,yp=function(e,t,n,r,o){var i=e.formatter.get(n),a=e.dom;if(i&&t)for(var u=0;u<i.length;u++){var s=i[u];if(Pg(e.dom,t,s)&&Lg(a,t,s,"attributes",o,r)&&Lg(a,t,s,"styles",o,r)){var c=s.classes;if(c)for(var l=0;l<c.length;l++)if(!e.dom.hasClass(t,al(c[l],r)))return;return s}}},Cp=So,xp="_mce_caret",wp={},Sp=fe,Np=ce;function Ep(e){return Hn(e)&&!Qc(e)&&!Vc(e)&&!sn(e)}function kp(e,t){for(var n=e;n;n=n[t]){if(Vn(n)&&Be(n.data))return e;if(Hn(n)&&!Qc(n))return n}return e}function _p(e,t,n){var r=tm(e);if(t&&n&&(t=kp(t,"previousSibling"),n=kp(n,"nextSibling"),r.compare(t,n))){for(var o=t.nextSibling;o&&o!==n;){var i=o,o=o.nextSibling;t.appendChild(i)}return e.remove(n),Nt.each(Nt.grep(n.childNodes),function(e){t.appendChild(e)}),t}return n}function Ap(e,t,n,r){var o;r&&!1!==t.merge_siblings&&(o=_p(e,rl(r),r),_p(e,o,rl(o,!0)))}function Rp(t,n){return function(e){return!(!e||!cl(t,e,n))}}function Dp(r,o,i){return function(e){var t,n;r.setStyle(e,o,i),""===e.getAttribute("style")&&e.removeAttribute("style"),t=r,"SPAN"===(n=e).nodeName&&0===t.getAttribs(n).length&&t.remove(n,!0)}}function Tp(e,t,n){return e.isChildOf(t,n)&&t!==n&&!e.isBlock(n)}function Op(e,t,n){var r,o=t[n?"startContainer":"endContainer"],i=t[n?"startOffset":"endOffset"];return Hn(o)&&(r=o.childNodes.length-1,!n&&i&&i--,o=o.childNodes[r<i?r:i]),Vn(o)&&n&&i>=o.nodeValue.length&&(o=new Dr(o,e.getBody()).next()||o),Vn(o)&&!n&&0===i&&new Dr(o,e.getBody()).prev()||o}function Bp(e,t){var n=t?"firstChild":"lastChild";if(/^(TR|TH|TD)$/.test(e.nodeName)&&e[n]){var r=e[n];return"TR"===e.nodeName&&r[n]||r}return e}function Pp(e,t,n,r){var o=e.create(n,r);return t.parentNode.insertBefore(o,t),o.appendChild(t),o}function Lp(e,t,n,r,o){var i=Et.fromDom(t),a=Et.fromDom(e.create(r,o));return Kt(a,(n?It:Lt)(i)),n?(qt(i,a),Wt(a,i)):($t(i,a),Ln(a,i)),a.dom}function Ip(e,t,n,r){var o=rl(t,n,r);return K(o)||"BR"===o.nodeName||e.isBlock(o)}function Mp(e,r,o,t,i){var n,a,u=e.dom,s=u,c=t;if(!(pl(a=r)&&Rh(c,a.inline)||ml(a)&&Rh(c,a.block)||gl(a)&&(Hn(c)&&s.is(c,a.selector))||r.links&&"A"===t.nodeName))return kh.keep();var l,f,d,m,g,p,h,v,b=t;if(pl(r)&&"all"===r.remove&&S(r.preserve_attributes)){var y=U(u.getAttribs(b),function(e){return T(r.preserve_attributes,e.name.toLowerCase())});if(u.removeAllAttribs(b),Y(y,function(e){return u.setAttrib(b,e.name,e.value)}),0<y.length)return kh.rename("span")}if("all"!==r.remove){Ah(r.styles,function(e,t){e=sl(u,al(e,o),t+""),N(t)&&(t=e,i=null),!r.remove_similar&&i&&!Rh(cl(u,i,t),e)||u.setStyle(b,t,""),n=!0}),n&&""===u.getAttrib(b,"style")&&(b.removeAttribute("style"),b.removeAttribute("data-mce-style")),Ah(r.attributes,function(e,t){var n;if(e=al(e,o),N(t)&&(t=e,i=null),r.remove_similar||!i||Rh(u.getAttrib(i,t),e))if("class"===t&&(e=u.getAttrib(b,t))&&(n="",Y(e.split(/\s+/),function(e){/mce\-\w+/.test(e)&&(n+=(n?" ":"")+e)}),n))u.setAttrib(b,t,n);else{if(_h.test(t)&&b.removeAttribute("data-mce-"+t),"style"===t&&on(["li"])(b)&&"none"===u.getStyle(b,"list-style-type"))return b.removeAttribute(t),void u.setStyle(b,"list-style-type","none");"class"===t&&b.removeAttribute("className"),b.removeAttribute(t)}}),Ah(r.classes,function(e){e=al(e,o),i&&!u.hasClass(i,e)||u.removeClass(b,e)});for(var C=u.getAttribs(b),x=0;x<C.length;x++){var w=C[x].nodeName;if(0!==w.indexOf("_")&&0!==w.indexOf("data-"))return kh.keep()}}return"none"!==r.remove?(l=e,d=r,p=(f=b).parentNode,h=l.dom,v=ks(l),ml(d)&&(v?p===h.getRoot()&&(d.list_block&&Rh(f,d.list_block)||Y(xe(f.childNodes),function(e){il(l,v,e.nodeName.toLowerCase())?m?m.appendChild(e):(m=Pp(h,e,v),h.setAttribs(m,l.settings.forced_root_block_attrs)):m=null})):h.isBlock(f)&&!h.isBlock(p)&&(Ip(h,f,!1)||Ip(h,f.firstChild,!0,!0)||f.insertBefore(h.create("br"),f.firstChild),Ip(h,f,!0)||Ip(h,f.lastChild,!1,!0)||f.appendChild(h.create("br")))),gl(g=d)&&pl(g)&&fn(ue(g,"mixed"),!0)&&!Rh(d.inline,f)||h.remove(f,!0),kh.removed()):kh.keep()}function Fp(t,e,n,r,o){return Mp(t,e,n,r,o).fold(D,function(e){return t.dom.rename(r,e),!0},w)}function Up(u,s,c,e,l){function a(e){var n,r,o,i,a,t=(r=s,o=c,i=l,Y(fl((n=u).dom,e.parentNode).reverse(),function(e){var t;a||"_start"===e.id||"_end"===e.id||(t=yp(n,e,r,o,i))&&!1!==t.split&&(a=e)}),a);return function(e,t,n,r,o,i,a,u){var s,c,l=e.dom;if(n){for(var f=n.parentNode,d=r.parentNode;d&&d!==f;d=d.parentNode){for(var m=l.clone(d,!1),g=0;g<t.length&&null!==(m=function(t,e,n){return Mp(t,e,u,n,n).fold(J(n),function(e){return t.dom.createFragment().appendChild(n),t.dom.rename(n,e)},J(null))}(e,t[g],m));g++);m&&(s&&m.appendChild(s),c=c||m,s=m)}!i||a.mixed&&l.isBlock(n)||(r=l.split(n,r)),s&&(o.parentNode.insertBefore(s,o),c.appendChild(o),pl(a)&&Ap(l,a,0,s))}return r}(u,m,t,e,e,!0,g,c)}function f(t){return F(m,function(e){return Fp(u,e,c,t,t)})}function d(e){var t,n=h.get(e?"_start":"_end"),r=n[e?"firstChild":"lastChild"];return Qc(t=r)&&Hn(t)&&("_start"===t.id||"_end"===t.id)&&(r=r[e?"firstChild":"lastChild"]),Vn(r)&&0===r.data.length&&(r=e?n.previousSibling||n.nextSibling:n.nextSibling||n.previousSibling),h.remove(n,!0),r}function t(e){var t=kl(u,e,m,e.collapsed);if(g.split){if(t=Pf(t),(r=Op(u,t,!0))!==(o=Op(u,t))){if(r=Bp(r,!0),o=Bp(o,!1),Tp(h,r,o)){var n=ve.from(r.firstChild).getOr(r);return a(Lp(h,n,!0,"span",{id:"_start","data-mce-type":"bookmark"})),void d(!0)}if(Tp(h,o,r))return n=ve.from(o.lastChild).getOr(o),a(Lp(h,n,!1,"span",{id:"_end","data-mce-type":"bookmark"})),void d(!1);var r=Pp(h,r,"span",{id:"_start","data-mce-type":"bookmark"}),o=Pp(h,o,"span",{id:"_end","data-mce-type":"bookmark"}),i=h.createRng();i.setStartAfter(r),i.setEndBefore(o),_l(h,i,function(e){Y(e,function(e){Qc(e)||Qc(e.parentNode)||a(e)})}),a(r),a(o),r=d(!0),o=d()}else r=o=a(r);t.startContainer=r.parentNode||r,t.startOffset=h.nodeIndex(r),t.endContainer=o.parentNode||o,t.endOffset=h.nodeIndex(o)+1}_l(h,t,function(e){Y(e,v)})}var n,m=u.formatter.get(s),g=m[0],p=!0,h=u.dom,r=u.selection,v=function(t){var e=!0,n=!1;Hn(t)&&h.getContentEditable(t)&&(e=p,p="true"===h.getContentEditable(t),n=!0);var r,o,i=xe(t.childNodes);if(p&&!n&&(r=f(t)||F(m,function(e){return Pg(h,t,e)}),o=t.parentNode,!r&&V(o)&&hl(g)&&f(o)),g.deep&&i.length){for(var a=0;a<i.length;a++)v(i[a]);n&&(p=e)}Y(["underline","line-through","overline"],function(e){Hn(t)&&u.dom.getStyle(t,"text-decoration")===e&&t.parentNode&&ll(h,t.parentNode)===e&&Fp(u,{deep:!1,exact:!0,inline:"span",styles:{textDecoration:e}},null,t)})};if(e)return tl(e)?((n=h.createRng()).setStartBefore(e),n.setEndAfter(e),t(n)):t(e),void wf(u,s,e,c);if("false"!==h.getContentEditable(r.getNode()))r.isCollapsed()&&pl(g)&&!Dl(u).length?$g(u,s,c,l):(Il(r,!0,function(){Ll(u,t)}),pl(g)&&Ig(u,s,c,r.getStart())&&nl(h,r,r.getRng()),u.nodeChanged()),wf(u,s,e,c);else{e=r.getNode();for(var o=0;o<m.length&&(!m[o].ceFalseOverride||!Fp(u,m[o],c,e,e));o++);wf(u,s,e,c)}}function zp(e){return Hn(e)&&!Qc(e)&&!Vc(e)&&!sn(e)}function Hp(e){return Ee(e,"vars")}function jp(n,e,r,o,i){return I(e,function(e){var t=n.formatter.matchNode(e,r,null!=i?i:{},o);return!b(t)},function(e){return Og(n,e,r)||!o&&V(n.formatter.matchNode(e,r,i,!0))})}function Vp(e,t){var n=null!=t?t:Bh(e);return U(fl(e.dom,n),function(e){return Hn(e)&&!sn(e)})}function qp(e,o,i,a,t,n){var r,u,s,c,l,f,d,m,g;return null===o.get()&&(u=e,(r=o).set({}),u.on("NodeChange",function(e){Ph(u,e.element,r.get())}),u.on("FormatApply FormatRemove",function(e){var t=ve.from(e.node).map(function(e){return tl(e)?e:e.startContainer}).bind(function(e){return Hn(e)?ve.some(e):ve.from(e.parentElement)}).getOrThunk(function(){return Bh(u)});Ph(u,t,r.get())})),s=e,l=i,f=a,d=t,m=n,g=(c=o).get(),Y(l.split(","),function(t){function e(){var e=Vp(s);return jp(s,e,t,d,m).isSome()}var n,r=ue(g,t).getOrThunk(function(){var e={withSimilar:{state:au(!1),similar:!0,callbacks:[]},withoutSimilar:{state:au(!1),similar:!1,callbacks:[]},withVars:[]};return g[t]=e});b(m)?((n=d?r.withSimilar:r.withoutSimilar).callbacks.push(f),1===n.callbacks.length&&n.state.set(e())):r.withVars.push({state:au(e()),similar:d,vars:m,callback:f})}),c.set(g),{unbind:function(){var e,t=i,n=a,r=(e=o).get();Y(t.split(","),function(t){return ue(r,t).each(function(e){r[t]={withSimilar:_e(_e({},e.withSimilar),{callbacks:U(e.withSimilar.callbacks,function(e){return e!==n})}),withoutSimilar:_e(_e({},e.withoutSimilar),{callbacks:U(e.withoutSimilar.callbacks,function(e){return e!==n})}),withVars:U(e.withVars,function(e){return e.callback!==n})}})}),e.set(r)}}}function $p(e,t){var n=(t||document).createDocumentFragment();return Y(e,function(e){n.appendChild(e.dom)}),Et.fromDom(n)}function Wp(e,t,n){return{element:e,width:t,rows:n}}function Kp(e,t){return{element:e,cells:t}}function Xp(e,t){var n=parseInt(vn(e,t),10);return isNaN(n)?1:n}function Yp(e){return L(e,function(e,t){return t.cells.length>e?t.cells.length:e},0)}function Gp(e,t){for(var n=e.rows,r=0;r<n.length;r++)for(var o=n[r].cells,i=0;i<o.length;i++)if(je(o[i],t))return ve.some({x:i,y:r});return ve.none()}function Jp(e,t,n,r,o){for(var i=[],a=e.rows,u=n;u<=o;u++){var s=a[u].cells,c=t<r?s.slice(t,r+1):s.slice(r,t+1);i.push(Kp(a[u].element,c))}return i}function Qp(e){var o=Wp(Eu(e),0,[]);return Y(yu(e,"tr"),function(n,r){Y(yu(n,"td,th"),function(e,t){!function(e,t,n,r,o){for(var i=Xp(o,"rowspan"),a=Xp(o,"colspan"),u=e.rows,s=n;s<n+i;s++){u[s]||(u[s]=Kp(ku(r),[]));for(var c=t;c<t+a;c++)u[s].cells[c]=s===n&&c===t?o:Eu(o)}}(o,function(e,t,n){for(;r=t,((o=e.rows)[n]?o[n].cells:[])[r];)t++;var r,o;return t}(o,t,r),r,n,e)})}),Wp(o.element,Yp(o.rows),o.rows)}function Zp(e,t){var n,r,o,i=Et.fromDom(t.commonAncestorContainer),a=ym(i,e),u=U(a,function(e){return Br(e)||mo(e)}),s=(o=t,M(r=a,function(e){return"li"===kt(e)&&Ol(e,o)}).fold(J([]),function(e){return M(r,function(e){return"ul"===kt(e)||"ol"===kt(e)}).map(function(e){var t=Et.fromTag(kt(e));return xn(t,ae(Nn(e),function(e,t){return Ge(t,"list-style")})),[Et.fromTag("li"),t]}).getOr([])}));return A(u.concat(s.length?s:vo(n=i)?Ot(n).filter(ho).fold(J([]),function(e){return[n,e]}):ho(n)?[n]:[]),Eu)}function eh(){return $p([])}function th(e,i){return vr(i[0],"table",R(je,e)).bind(function(e){var s,t,n=i[0],r=i[i.length-1],o=Qp(e);return t=r,Gp(s=o,n).bind(function(u){return Gp(s,t).map(function(e){return t=s,n=u.x,r=u.y,o=e.x,a=r<(i=e.y)?Jp(t,n,r,o,i):Jp(t,n,i,o,r),Wp(t.element,Yp(a),a);var t,n,r,o,i,a})}).map(function(e){return $p([(n=A((t=e).rows,function(e){var t=A(e.cells,function(e){var t=ku(e);return Cn(t,"colspan"),Cn(t,"rowspan"),t}),n=Eu(e.element);return Kt(n,t),n}),r=Eu(t.element),Kt(o=Et.fromTag("tbody"),n),Ln(r,o),r)]);var t,n,r,o})}).getOrThunk(eh)}function nh(e,t){var n,r,o,i,a,u,s,c=Rl(t,e);return 0<c.length?th(e,c):(n=e,0<(r=t).length&&r[0].collapsed?eh():(o=n,i=r[0],a=Et.fromDom(i.cloneContents()),s=L(u=Zp(o,i),function(e,t){return Ln(t,e),t},a),0<u.length?$p([s]):s))}function rh(e,t){return 0<=t&&t<e.length&&Zc(e.charAt(t))}function oh(e,t){var n=Eo(e.innerText);return t?n.replace(/^[ \f\n\r\t\v]+/,""):n}function ih(e){return Hn(e)?e.outerHTML:Vn(e)?Zo.encodeRaw(e.data,!1):qn(e)?"\x3c!--"+e.data+"--\x3e":""}function ah(e,c){var l=0;Y(e,function(e){var t,n,r,o,i,a,u,s;0===e[0]?l++:1===e[0]?(o=c,i=e[1],a=l,s=function(e){var t,n=document.createElement("div"),r=document.createDocumentFragment();for(e&&(n.innerHTML=e);t=n.firstChild;)r.appendChild(t);return r}(i),o.hasChildNodes()&&a<o.childNodes.length?(u=o.childNodes[a]).parentNode.insertBefore(s,u):o.appendChild(s),l++):2===e[0]&&(n=l,(t=c).hasChildNodes()&&n<t.childNodes.length&&(r=t.childNodes[n]).parentNode.removeChild(r))})}function uh(e){var t=e.serializer.getTempAttrs(),n=em(e.getBody(),t);return null!==n.querySelector("iframe")?{type:"fragmented",fragments:U(A(xe(n.childNodes),i(Eo,ih)),function(e){return 0<e.length}),content:"",bookmark:null,beforeBookmark:null}:{type:"complete",fragments:null,content:Eo(n.innerHTML),bookmark:null,beforeBookmark:null}}function sh(e,t,n){var r,o,i,g,p,a,h,v,c,l,u,s=n?t.beforeBookmark:t.bookmark;function b(e,t,n,r){for(var o=e;o-t<r&&o<n&&g[o]===p[o-t];)++o;return{start:e,end:o,diag:t}}"fragmented"===t.type?(r=t.fragments,o=e.getBody(),i=A(xe(o.childNodes),ih),ah((p=r,a=(g=i).length+p.length+2,h=new Array(a),v=new Array(a),c=function(e,t,n,r,o){var i=l(e,t,n,r);if(null===i||i.start===t&&i.diag===t-r||i.end===e&&i.diag===e-n)for(var a=e,u=n;a<t||u<r;)a<t&&u<r&&g[a]===p[u]?(o.push([0,g[a]]),++a,++u):r-n<t-e?(o.push([2,g[a]]),++a):(o.push([1,p[u]]),++u);else{c(e,i.start,n,i.start-i.diag,o);for(var s=i.start;s<i.end;++s)o.push([0,g[s]]);c(i.end,t,i.end-i.diag,r,o)}},l=function(e,t,n,r){var o=t-e,i=r-n;if(0==o||0==i)return null;var a,u,s,c,l,f=o-i,d=i+o,m=(d%2==0?d:1+d)/2;for(h[1+m]=e,v[1+m]=t+1,a=0;a<=m;++a){for(u=-a;u<=a;u+=2){for(s=u+m,u===-a||u!==a&&h[s-1]<h[s+1]?h[s]=h[s+1]:h[s]=h[s-1]+1,l=(c=h[s])-e+n-u;c<t&&l<r&&g[c]===p[l];)h[s]=++c,++l;if(f%2!=0&&f-a<=u&&u<=f+a&&v[s-f]<=h[s])return b(v[s-f],u+e-n,t,r)}for(u=f-a;u<=f+a;u+=2){for(s=u+m-f,u===f-a||u!==f+a&&v[s+1]<=v[s-1]?v[s]=v[s+1]-1:v[s]=v[s-1],l=(c=v[s]-1)-e+n-u;e<=c&&n<=l&&g[c]===p[l];)v[s]=c--,l--;if(f%2==0&&-a<=u&&u<=a&&v[s]<=h[s+f])return b(v[s],u+e-n,t,r)}}},u=[],c(0,g.length,0,p.length,u),u),o)):e.setContent(t.content,{format:"raw",no_selection:!V(s)||!$c(s)||!s.isFakeCaret}),e.selection.moveToBookmark(s)}function ch(e){return"fragmented"===e.type?e.fragments.join(""):e.content}function lh(e){var t=Et.fromTag("body",Lh());return Su(t,ch(e)),Y(yu(t,"*[data-mce-bogus]"),Yt),t.dom.innerHTML}function fh(e,t){return!(!e||!t)&&(r=t,ch(e)===ch(r)||(n=t,lh(e)===lh(n)));var n,r}function dh(e){return 0===e.get()}function mh(e,t,n){dh(n)&&(e.typing=t)}function gh(e,t){e.typing&&(mh(e,!1,t),e.add())}function ph(c){return{undoManager:{beforeChange:function(e,t){var n=c,r=t;dh(e)&&r.set(hc(n.selection))},add:function(e,t,n,r,o,i){return function(e,t,n,r,o,i,a){var u=uh(e);if(i=Nt.extend(i=i||{},u),!1===dh(r)||e.removed)return null;var s=t.data[n.get()];if(e.fire("BeforeAddUndo",{level:i,lastLevel:s,originalEvent:a}).isDefaultPrevented())return null;if(s&&fh(s,i))return null;t.data[n.get()]&&o.get().each(function(e){t.data[n.get()].beforeBookmark=e});var c=e.getParam("custom_undo_redo_levels",0,"number");if(c&&t.data.length>c){for(var l=0;l<t.data.length-1;l++)t.data[l]=t.data[l+1];t.data.length--,n.set(t.data.length)}i.bookmark=hc(e.selection),n.get()<t.data.length-1&&(t.data.length=n.get()+1),t.data.push(i),n.set(t.data.length-1);var f={level:i,lastLevel:s,originalEvent:a};return 0<n.get()?(e.setDirty(!0),e.fire("AddUndo",f),e.fire("change",f)):e.fire("AddUndo",f),i}(c,e,t,n,r,o,i)},undo:function(e,t,n){return r=c,i=t,a=n,(o=e).typing&&(o.add(),o.typing=!1,mh(o,!1,i)),0<a.get()&&(a.set(a.get()-1),sh(r,u=o.data[a.get()],!0),r.setDirty(!0),r.fire("Undo",{level:u})),u;var r,o,i,a,u},redo:function(e,t){return n=c,o=t,(r=e).get()<o.length-1&&(r.set(r.get()+1),sh(n,i=o[r.get()],!1),n.setDirty(!0),n.fire("Redo",{level:i})),i;var n,r,o,i},clear:function(e,t){var n,r=c,o=t;(n=e).data=[],o.set(0),n.typing=!1,r.fire("ClearUndos")},reset:function(e){var t;(t=e).clear(),t.add()},hasUndo:function(e,t){return n=c,r=e,0<t.get()||r.typing&&r.data[0]&&!fh(uh(n),r.data[0]);var n,r},hasRedo:function(e,t){return n=e,t.get()<n.data.length-1&&!n.typing;var n},transact:function(e,t,n){return o=n,gh(r=e,t),r.beforeChange(),r.ignore(o),r.add();var r,o},ignore:function(e,t){try{e.set(e.get()+1),t()}finally{e.set(e.get()-1)}},extra:function(e,t,n,r){var o,i,a=c,u=t,s=r;(o=e).transact(n)&&(i=o.data[u.get()].bookmark,sh(a,o.data[u.get()-1],!0),o.transact(s)&&(o.data[u.get()-1].beforeBookmark=i))}},formatter:{match:function(e,t,n,r){return Ig(c,e,t,n,r)},matchAll:function(e,t){return o=e,i=t,a=[],u={},n=(r=c).selection.getStart(),r.dom.getParent(n,function(e){for(var t=0;t<o.length;t++){var n=o[t];!u[n]&&yp(r,e,n,i)&&(u[n]=!0,a.push(n))}},r.dom.getRoot()),a;var r,o,i,a,u,n},matchNode:function(e,t,n,r){return yp(c,e,t,n,r)},canApply:function(u){return function(e){var t=e.formatter.get(u),n=e.dom;if(t)for(var r=fl(n,e.selection.getStart()),o=t.length-1;0<=o;o--){var i=t[o];if(!gl(i)||V(i.defaultBlock))return!0;for(var a=r.length-1;0<=a;a--)if(n.is(r[a],i.selector))return!0}return!1}(c)},closest:function(e){return r=c,o=e,ve.from(r.selection.getStart(!0)).bind(function(e){return Tg(Et.fromDom(e),function(n){return ee(o,function(e){return yp(r,n.dom,t=e)?ve.some(t):ve.none();var t})},t)}).getOrNull();function t(e){return je(e,Et.fromDom(r.getBody()))}var r,o},apply:function(e,t,n){return Oh(c,e,t,n)},remove:function(e,t,n,r){return Up(c,e,t,n,r)},toggle:function(e,t,n){var r,o=e,i=t,a=n,u=(r=c).formatter.get(o);(!Ig(r,o,i,a)||"toggle"in u[0]&&!u[0].toggle?Oh:Up)(r,o,i,a)},formatChanged:function(e,t,n,r,o){return qp(c,e,t,n,r,o)}},editor:{getContent:function(e,t){return d=c,m=e,g=t,ve.from(d.getBody()).fold(J("tree"===m.format?new jd("body",11):""),function(e){return t=d,r=e,o=g,c=_e(_e({},n=m),{format:o,get:!0,getInner:!0}),l=n.no_events?c:t.fire("BeforeGetContent",c),f="raw"===l.format?Nt.trim(Eo(em(r,t.serializer.getTempAttrs()).innerHTML)):"text"===l.format?t.dom.isEmpty(r)?"":Eo(r.innerText||r.textContent):"tree"===l.format?t.serializer.serialize(r,l):(a=(i=t).serializer.serialize(r,l),u=ks(i),s=new RegExp("^(<"+u+"[^>]*>( | |\\s|\xa0|<br \\/>|)<\\/"+u+">[\r\n]*|<br \\/>[\r\n]*)$"),a.replace(s,"")),T(["text","tree"],l.format)||Co(Et.fromDom(r))?l.content=f:l.content=Nt.trim(f),(l.no_events?l:t.fire("GetContent",l)).content;var t,n,r,o,i,a,u,s,c,l,f});var d,m,g},setContent:function(e,t){return Rg(c,e,t)},insertContent:function(e,t){return kg(c,e,t)},addVisual:function(e){var i,t=e,a=(i=c).dom,n=V(t)?t:i.getBody();b(i.hasVisual)&&(i.hasVisual=i.getParam("visual",!0,"boolean")),Y(a.select("table,a",n),function(e){switch(e.nodeName){case"TABLE":var t=i.getParam("visual_table_class","mce-item-table","string"),n=a.getAttrib(e,"border");n&&"0"!==n||!i.hasVisual?a.removeClass(e,t):a.addClass(e,t);break;case"A":var r,o;a.getAttrib(e,"href")||(r=a.getAttrib(e,"name")||e.id,o=i.getParam("visual_anchor_class","mce-item-anchor","string"),r&&i.hasVisual?a.addClass(e,o):a.removeClass(e,o))}}),i.fire("VisualAid",{element:t,hasVisual:i.hasVisual})}},selection:{getContent:function(e,t){return function(e,t,n){var r,o=(r=t,_e(_e({},n=void 0===n?{}:n),{format:r,get:!0,selection:!0})),i=e.fire("BeforeGetContent",o);if(i.isDefaultPrevented())return e.fire("GetContent",i),i.content;if("text"===i.format)return m=e,ve.from(m.selection.getRng()).map(function(e){var t=ve.from(m.dom.getParent(e.commonAncestorContainer,m.dom.isBlock)),n=m.getBody(),r=t.map(function(e){return e.nodeName}).getOr("div").toLowerCase(),o=xt.browser.isIE()&&"pre"!==r,i=m.dom.add(n,r,{"data-mce-bogus":"all",style:"overflow: hidden; opacity: 0;"},e.cloneContents()),a=oh(i,o),u=Eo(i.textContent);if(m.dom.remove(i),rh(u,0)||rh(u,u.length-1)){var s=oh(t.getOr(n),o),c=s.indexOf(a);return-1===c?a:(rh(s,c-1)?" ":"")+a+(rh(s,c+a.length)?" ":"")}return a}).getOr("");i.getInner=!0;var a,u,s,c,l,f,d,m,g=(u=i,s=(a=e).selection.getRng(),c=a.dom.create("body"),l=a.selection.getSel(),f=Ed(a,Al(l)),(d=u.contextual?nh(Et.fromDom(a.getBody()),f).dom:s.cloneContents())&&c.appendChild(d),a.selection.serializer.serialize(c,u));return"tree"===i.format?g:(i.content=e.selection.isCollapsed()?"":g,e.fire("GetContent",i),i.content)}(c,e,t)}},raw:{getModel:function(){return ve.none()}}}}function hh(e){return Ee(e.plugins,"rtc")}function vh(e){var u=e;return ue(e.plugins,"rtc").bind(function(e){return ve.from(e.setup)}).fold(function(){return u.rtcInstance=ph(e),ve.none()},function(e){var t,n;return u.rtcInstance=(t=J(null),n=J(""),{undoManager:{beforeChange:te,add:t,undo:t,redo:t,clear:te,reset:te,hasUndo:D,hasRedo:D,transact:t,ignore:te,extra:te},formatter:{match:D,matchAll:J([]),matchNode:J(void 0),canApply:D,closest:n,apply:te,remove:te,toggle:te,formatChanged:J({unbind:te})},editor:{getContent:n,setContent:n,insertContent:te,addVisual:te},selection:{getContent:n},raw:{getModel:J(ve.none())}}),ve.some(function(){return e().then(function(e){return u.rtcInstance=(i=e.undoManager,a=e.formatter,n=e.editor,r=e.selection,t=e.raw,{undoManager:{beforeChange:i.beforeChange,add:i.add,undo:i.undo,redo:i.redo,clear:i.clear,reset:i.reset,hasUndo:i.hasUndo,hasRedo:i.hasRedo,transact:function(e,t,n){return i.transact(n)},ignore:function(e,t){return i.ignore(t)},extra:function(e,t,n,r){return i.extra(n,r)}},formatter:{match:function(e,t,n,r){return a.match(e,o(t),r)},matchAll:a.matchAll,matchNode:a.matchNode,canApply:function(e){return a.canApply(e)},closest:function(e){return a.closest(e)},apply:function(e,t,n){return a.apply(e,o(t))},remove:function(e,t,n,r){return a.remove(e,o(t))},toggle:function(e,t,n){return a.toggle(e,o(t))},formatChanged:function(e,t,n,r,o){return a.formatChanged(t,n,r,o)}},editor:{getContent:function(e,t){return n.getContent(e)},setContent:function(e,t){return n.setContent(e,t)},insertContent:function(e,t){return n.insertContent(e)},addVisual:n.addVisual},selection:{getContent:function(e,t){return r.getContent(t)}},raw:{getModel:function(){return ve.some(t.getRawModel())}}}),e.rtc.isRemote;function o(e){return h(e)?e:{}}var i,a,n,r,t})})})}function bh(e){return e.rtcInstance||ph(e)}function yh(e){var t=e.rtcInstance;if(t)return t;throw new Error("Failed to get RTC instance not yet initialized.")}function Ch(e){return 0===e.dom.length?(In(e),ve.none()):ve.some(e)}function xh(e,t,u,s){e.bind(function(a){return(s?jm:Hm)(a.dom,s?a.dom.length:0),t.filter(An).map(function(e){var t=u,n=s,r=a.dom,o=e.dom,i=(n?r:o).length;n?(Vm(r,o,!1,!n),t.setStart(o,i)):(Vm(o,r,!1,!n),t.setEnd(o,i))})}).orThunk(function(){var e=s;return t.filter(function(e){return Hl.isBookmarkNode(e.dom)}).bind(e?Pt:Bt).or(t).filter(An).map(function(e){var n,r=s;Ot(n=e).each(function(e){var t=n.dom;r&&Bm(e,cs(t,0))?Hm(t,0):!r&&Pm(e,cs(t,t.length))&&jm(t,t.length)})})})}function wh(e,t,n){var r,o=(r=t,_e(_e({format:"html"},n=void 0===n?{}:n),{set:!0,selection:!0,content:r})),i=o;if(!o.no_events){var a=e.fire("BeforeSetContent",o);if(a.isDefaultPrevented())return void e.fire("SetContent",a);i=a}i.content=function(e,t){if("raw"===t.format)return t.content;var n=e.selection.getRng(),r=e.dom.getParent(n.commonAncestorContainer,e.dom.isBlock),o=r?{context:r.nodeName.toLowerCase()}:{},i=e.parser.parse(t.content,_e(_e({isRootContent:!0,forced_root_block:!1},o),t));return rm({validate:e.validate},e.schema).serialize(i)}(e,i);var u=e.selection.getRng();!function(e,t){var n=ve.from(t.firstChild).map(Et.fromDom),r=ve.from(t.lastChild).map(Et.fromDom);e.deleteContents(),e.insertNode(t);var o=n.bind(Bt).filter(An).bind(Ch),i=r.bind(Pt).filter(An).bind(Ch);xh(o,n,e,!0),xh(i,r,e,!1),e.collapse(!1)}(u,u.createContextualFragment(i.content)),e.selection.setRng(u),nd(e,u),i.no_events||e.fire("SetContent",i)}function Sh(e,t,n){var r;e&&Ee(e,t)&&(0===(r=U(e[t],function(e){return e!==n})).length?delete e[t]:e[t]=r)}Kg=function(e){var t,n=e.selection.getRng(),r=on(["pre"]);n.collapsed||(t=e.selection.getSelectedBlocks(),Np(Sp(Sp(t,r),function(e){return r(e.previousSibling)&&-1!==de(t,e.previousSibling)}),function(e){var t,n=e.previousSibling;Ya(t=e).remove(),Ya(n).append("<br><br>").append(t.childNodes)}))},wp["pre"]||(wp.pre=[]),wp.pre.push(Kg);var Nh=Nt.each,Eh=function(e,t,n){Nh(e.childNodes,function(e){Ep(e)&&(t(e)&&n(e),e.hasChildNodes()&&Eh(e,t,n))})},kh=ir([{keep:[]},{rename:["name"]},{removed:[]}]),_h=/^(src|href|style)$/,Ah=Nt.each,Rh=ul,Dh=Nt.each,Th=Nt.each,Oh=function(S,N,E,r){function k(n,e){var t;y((e=void 0===e?A:e).onformat)&&e.onformat(n,e,E,r),Th(e.styles,function(e,t){u.setStyle(n,t,al(e,E))}),!e.styles||(t=u.getAttrib(n,"style"))&&u.setAttrib(n,"data-mce-style",t),Th(e.attributes,function(e,t){u.setAttrib(n,t,al(e,E))}),Th(e.classes,function(e){e=al(e,E),u.hasClass(n,e)||u.addClass(n,e)})}function g(e,t){var n=!1;return Th(e,function(e){return!!gl(e)&&(V(e.collapsed)&&e.collapsed!==a||!u.is(t,e.selector)||Vc(t)?void 0:(k(t,e),!(n=!0)))}),n}function o(x,e,l){var w=[],f=!0,d=A.inline||A.block,m=function(e){if(X(e)){var t=u.create(e);return k(t),t}return null}(d);_l(x,e,function(e){var s,c=function(e){var t=!1,n=f,r=e.nodeName.toLowerCase(),o=e.parentNode,i=o.nodeName.toLowerCase();if(Hn(e)&&x.getContentEditable(e)&&(n=f,f="true"===x.getContentEditable(e),t=!0),Kn(e)&&!function(e,t,n,r){if(e.getParam("format_empty_lines",!1,"boolean")&&pl(t)){var o=no(e.schema),i=(a=Et.fromDom(n),s=function(e){return Vc(e.dom)},((c=(u=a).dom).parentNode?kr(Et.fromDom(c.parentNode),function(e){return!je(u,e)&&s(e)}):ve.none()).isSome());return se(o,r)&&Kr(Et.fromDom(n.parentNode),!1)&&!i}var a,u,s,c}(S,A,e,i))return s=null,void(ml(A)&&x.remove(e));if(ml(A)&&A.wrapper&&yp(S,e,N,E))s=null;else{if(f&&!t&&ml(A)&&!A.wrapper&&ol(S,r)&&il(S,i,d)){var a=x.rename(e,d);return k(a),w.push(a),void(s=null)}if(gl(A)){var u=g(_,e);if(!u&&V(o)&&hl(A)&&(u=g(_,o)),!pl(A)||u)return void(s=null)}!f||t||!il(S,d,r)||!il(S,i,d)||!l&&Vn(e)&&No(e.data)||Vc(e)||pl(A)&&x.isBlock(e)?(s=null,Y(xe(e.childNodes),c),t&&(f=n),s=null):(s||(s=x.clone(m,!1),e.parentNode.insertBefore(s,e),w.push(s)),s.appendChild(e))}};Y(e,c)}),!0===A.links&&Y(w,function(e){var t=function(e){"A"===e.nodeName&&k(e,A),Y(xe(e.childNodes),t)};t(e)}),Y(w,function(e){var n,t,r,o,i,a,u,s,c,l,f,d,m,g,p,h,v,b,y=(n=0,Y(e.childNodes,function(e){var t;V(t=e)&&Vn(t)&&0===t.length||Qc(e)||n++}),n);function C(e){var t;1===e.nodeType&&e.parentNode&&1===e.parentNode.nodeType&&(t=ll(m,e.parentNode),m.getStyle(e,"color")&&t?m.setStyle(e,"text-decoration",t):m.getStyle(e,"text-decoration")===t&&m.setStyle(e,"text-decoration",null))}!(1<w.length)&&x.isBlock(e)||0!==y?(pl(A)||ml(A)&&A.wrapper)&&(A.exact||1!==y||(e=M((d=e).childNodes,zp).filter(function(e){return Pg(x,e,A)}).map(function(e){var t=x.clone(e,!1);return k(t),x.replace(t,d,!0),x.remove(e,!0),t}).getOr(d)),h=S,v=E,b=e,Dh(_,function(t){var r,e,n;pl(t)&&Dh(h.dom.select(t.inline,b),function(e){Ep(e)&&Fp(h,t,v,e,t.exact?e:null)}),r=h.dom,(e=t).clear_child_styles&&(n=e.links?"*:not(a)":"*",Nh(r.select(n,b),function(n){Ep(n)&&Nh(e.styles,function(e,t){r.setStyle(n,t,"")})}))}),s=A,yp(u=S,(f=e).parentNode,c=N,l=E)&&Fp(u,s,l,f)||s.merge_with_parents&&u.dom.getParent(f.parentNode,function(e){if(yp(u,e,c,l))return Fp(u,s,l,f),!0}),a=e,(i=A).styles&&i.styles.backgroundColor&&Eh(a,Rp(x,"fontSize"),Dp(x,"backgroundColor",al(i.styles.backgroundColor,E))),m=x,p=e,(g=A).styles&&(g.styles.color||g.styles.textDecoration)&&(Nt.walk(p,C,"childNodes"),C(p)),t=x,o=e,!pl(r=A)||"sub"!==r.inline&&"sup"!==r.inline||(Eh(o,Rp(t,"fontSize"),Dp(t,"fontSize","")),t.remove(t.select("sup"===r.inline?"sub":"sup",o),!0)),Ap(x,A,0,e)):x.remove(e,!0)})}var e,t,n,i,_=S.formatter.get(N),A=_[0],a=!r&&S.selection.isCollapsed(),u=S.dom,s=S.selection;if("false"!==u.getContentEditable(s.getNode()))A&&(r?tl(r)?g(_,r)||((e=u.createRng()).setStartBefore(r),e.setEndAfter(r),o(u,kl(S,e,_),!0)):o(u,r,!0):a&&pl(A)&&!Dl(S).length?function(e,t,n){var r,o=e.selection,i=o.getRng(),a=i.startOffset,u=i.startContainer.nodeValue,s=qc(e.getBody(),o.getStart());s&&(r=Fg(s));var c,l,f,d,m=/[^\s\u00a0\u00ad\u200b\ufeff]/;u&&0<a&&a<u.length&&m.test(u.charAt(a))&&m.test(u.charAt(a-1))?(c=o.getBookmark(),i.collapse(!0),l=Pf(kl(e,i,e.formatter.get(t))),e.formatter.apply(t,n,l),o.moveToBookmark(c)):(s&&r.nodeValue===Cp||(f=e.getDoc(),d=Ug(!0).dom,r=(s=f.importNode(d,!0)).firstChild,i.insertNode(s),a=1),e.formatter.apply(t,n,s),o.setCursorLocation(r,a))}(S,N,E):(t=s.getNode(),n=_[0],S.settings.forced_root_block||!n.defaultBlock||u.getParent(t,u.isBlock)||Oh(S,n.defaultBlock),s.setRng(Cg(s.getRng())),Il(s,!0,function(){Ll(S,function(e,t){var n=t?e:kl(S,e,_);o(u,n,!1)})}),nl(u,s,s.getRng()),S.nodeChanged()),i=S,Np(wp[N],function(e){e(i)})),xf(S,N,r,E);else{r=s.getNode();for(var c=0,l=_.length;c<l;c++){var f=_[c];if(f.ceFalseOverride&&gl(f)&&u.is(r,f.selector)){k(r,f);break}}xf(S,N,r,E)}},Bh=function(e){return e.selection.getStart()},Ph=function(i,a,e){var u=Vp(i,a);ne(e,function(e,o){function t(e){var t,n=jp(i,u,o,e.similar,Hp(e)?e.vars:void 0),r=n.isSome();e.state.get()!==r&&(e.state.set(r),t=n.getOr(a),Hp(e)?e.callback(r,{node:t,format:o,parents:u}):Y(e.callbacks,function(e){return e(r,{node:t,format:o,parents:u})}))}Y([e.withSimilar,e.withoutSimilar],t),Y(e.withVars,t)})},Lh=Re(function(){return document.implementation.createHTMLDocument("undo")});function Ih(e){return e.select}function Mh(e){return e&&e.ownerDocument&&Ve(Et.fromDom(e.ownerDocument),Et.fromDom(e))}function Fh(a,u,e,s){function t(e,t){return wh(s,e,t)}function n(){var e=c(),t=null==e?void 0:e.anchorNode,n=null==e?void 0:e.focusNode;if(!e||!t||!n||rn(t)||rn(n))return!0;var r=a.createRng();r.setStart(t,e.anchorOffset),r.collapse(!0);var o=a.createRng();return o.setStart(n,e.focusOffset),o.collapse(!0),r.compareBoundaryPoints(r.START_TO_START,o)<=0}function r(e){var t=p();t.collapse(!!e),h(t)}function c(){return u.getSelection?u.getSelection():u.document.selection}var l,f,o,i,d,m,g=function(e,t){return d||(d={},m={},i.on("NodeChange",function(e){var n=e.element,r=x(n),o={};Nt.each(d,function(e,n){C(n,r).each(function(t){m[n]||(Y(e,function(e){e(!0,{node:t,selector:n,parents:r})}),m[n]=e),o[n]=e})}),Nt.each(m,function(e,t){o[t]||(delete m[t],Nt.each(e,function(e){e(!1,{node:n,selector:t,parents:r})}))})})),d[e]||(d[e]=[]),d[e].push(t),C(e,x(i.selection.getStart())).each(function(){m[e]=d[e]}),{unbind:function(){Sh(d,e,t),Sh(m,e,t)}}},p=function(){function e(e,t,n){try{return t.compareBoundaryPoints(e,n)}catch(e){return-1}}var t,n,r,o=u.document;if(void 0!==s.bookmark&&!1===Cd(s)){var i=md(s);if(i.isSome())return i.map(function(e){return Ed(s,[e])[0]}).getOr(o.createRange())}try{(t=c())&&!rn(t.anchorNode)&&(n=0<t.rangeCount?t.getRangeAt(0):(t.createRange?t:o).createRange(),n=Ed(s,[n])[0])}catch(e){}return(n=n||(o.createRange?o.createRange():o.body.createTextRange())).setStart&&9===n.startContainer.nodeType&&n.collapsed&&(r=a.getRoot(),n.setStart(r,0),n.setEnd(r,0)),l&&f&&(0===e(n.START_TO_START,n,l)&&0===e(n.END_TO_END,n,l)?n=f:f=l=null),n},h=function(e,t){var n;if((r=e)&&(Ih(r)||Mh(r.startContainer)&&Mh(r.endContainer))){var r,o=Ih(e)?e:null;if(o){f=null;try{o.select()}catch(e){}}else{var i=c();if(e=s.fire("SetSelectionRange",{range:e,forward:t}).range,i){f=e;try{i.removeAllRanges(),i.addRange(e)}catch(e){}!1===t&&i.extend&&(i.collapse(e.endContainer,e.endOffset),i.extend(e.startContainer,e.startOffset)),l=0<i.rangeCount?i.getRangeAt(0):null}e.collapsed||e.startContainer!==e.endContainer||!i.setBaseAndExtent||xt.ie||e.endOffset-e.startOffset<2&&e.startContainer.hasChildNodes()&&(n=e.startContainer.childNodes[e.startOffset])&&"IMG"===n.tagName&&(i.setBaseAndExtent(e.startContainer,e.startOffset,e.endContainer,e.endOffset),i.anchorNode===e.startContainer&&i.focusNode===e.endContainer||i.setBaseAndExtent(n,0,n,1)),s.fire("AfterSetSelectionRange",{range:e,forward:t})}}},v={bookmarkManager:null,controlSelection:null,dom:o=a,win:u,serializer:e,editor:i=s,collapse:r,setCursorLocation:function(e,t){var n=a.createRng();V(e)&&V(t)?(n.setStart(e,t),n.setEnd(e,t),h(n),r(!1)):(Bl(a,n,s.getBody(),!0),h(n))},getContent:function(e){return n=(t=void 0===(t=e)?{}:t).format||"html",r=t,yh(s).selection.getContent(n,r);var t,n,r},setContent:t,getBookmark:function(e,t){return b.getBookmark(e,t)},moveToBookmark:function(e){return b.moveToBookmark(e)},select:function(e,t){var r=a,o=t;return ve.from(e).map(function(e){var t=r.nodeIndex(e),n=r.createRng();return n.setStart(e.parentNode,t),n.setEnd(e.parentNode,t+1),o&&(Bl(r,n,e,!0),Bl(r,n,e,!1)),n}).each(h),e},isCollapsed:function(){var e=p(),t=c();return!(!e||e.item)&&(e.compareEndPoints?0===e.compareEndPoints("StartToEnd",e):!t||e.collapsed)},isForward:n,setNode:function(e){return t(a.getOuterHTML(e)),e},getNode:function(){return function(e,t){if(!t)return e;var n=t.startContainer,r=t.endContainer,o=t.startOffset,i=t.endOffset,a=t.commonAncestorContainer;return!t.collapsed&&(n===r&&i-o<2&&n.hasChildNodes()&&(a=n.childNodes[o]),3===n.nodeType&&3===r.nodeType&&(n=n.length===o?Nd(n.nextSibling,!0):n.parentNode,r=0===i?Nd(r.previousSibling,!1):r.parentNode,n&&n===r))?n:a&&3===a.nodeType?a.parentNode:a}(s.getBody(),p())},getSel:c,setRng:h,getRng:p,getStart:function(e){return wd(s.getBody(),p(),e)},getEnd:function(e){return Sd(s.getBody(),p(),e)},getSelectedBlocks:function(e,t){return function(e,t,n,r){var o=[],i=e.getRoot();if(n=e.getParent(n||wd(i,t,t.collapsed),e.isBlock),r=e.getParent(r||Sd(i,t,t.collapsed),e.isBlock),n&&n!==i&&o.push(n),n&&r&&n!==r)for(var a,u=new Dr(n,i);(a=u.next())&&a!==r;)e.isBlock(a)&&o.push(a);return r&&n!==r&&r!==i&&o.push(r),o}(a,p(),e,t)},normalize:function(){var e=p();if(1<Al(c()).length||!Pl(s))return e;var t=Of(a,e);return t.each(function(e){h(e,n())}),t.getOr(e)},selectorChanged:function(e,t){return g(e,t),v},selectorChangedWithUnbind:g,getScrollContainer:function(){for(var e,t=a.getRoot();t&&"BODY"!==t.nodeName;){if(t.scrollHeight>t.clientHeight){e=t;break}t=t.parentNode}return e},scrollIntoView:function(e,t){V(e)?(s.inline?Zf:td)(s,e,t):nd(s,p(),t)},placeCaretAt:function(e,t){return h(Ef(e,t,s.getDoc()))},getBoundingClientRect:function(){var e=p();return e.collapsed?cs.fromRangeStart(e).getClientRects()[0]:e.getBoundingClientRect()},destroy:function(){u=l=f=null,y.destroy()}},b=Hl(v),y=Sf(v,s);function C(t,e){return M(e,function(e){return o.is(e,t)})}function x(e){return o.getParents(e,null,o.getRoot())}return v.bookmarkManager=b,v.controlSelection=y,v}function Uh(e,t){var n,r,a,u,o=ao();t.convert_fonts_to_spans&&(r=e,a=o,u=Nt.explode(t.font_size_legacy_values),r.addNodeFilter("font",function(e){Y(e,function(e){var t,n=a.parse(e.attr("style")),r=e.attr("color"),o=e.attr("face"),i=e.attr("size");r&&(n.color=r),o&&(n["font-family"]=o),i&&(n["font-size"]=u[parseInt(e.attr("size"),10)-1]),e.name="span",e.attr("style",a.serialize(n)),t=e,Y(["color","face","size"],function(e){t.attr(e,null)})})})),n=o,e.addNodeFilter("strike",function(e){Y(e,function(e){var t=n.parse(e.attr("style"));t["text-decoration"]="line-through",e.name="span",e.attr("style",n.serialize(t))})})}function zh(e){var t,n=decodeURIComponent(e).split(","),r=/data:([^;]+)/.exec(n[0]);return{type:t=r?r[1]:t,data:n[1]}}function Hh(e,t){var n;try{n=atob(t)}catch(e){return ve.none()}for(var r=new Uint8Array(n.length),o=0;o<r.length;o++)r[o]=n.charCodeAt(o);return ve.some(new Blob([r],{type:e}))}function jh(e){return 0===e.indexOf("blob:")?(o=e,new _r(function(e,t){function n(){t("Cannot convert "+o+" to Blob. Resource might not exist or is inaccessible.")}try{var r=new XMLHttpRequest;r.open("GET",o,!0),r.responseType="blob",r.onload=function(){200===r.status?e(r.response):n()},r.onerror=n,r.send()}catch(e){n()}})):0===e.indexOf("data:")?(n=e,new _r(function(e){var t=zh(n);Hh(t.type,t.data).fold(function(){return e(new Blob([]))},e)})):null;var o,n}function Vh(e){return(e||"blobid")+Yh++}function qh(r,d){var o={};return{findAll:function(e,n){n=n||w;var t=A(U(e?xe(e.getElementsByTagName("img")):[],function(e){var t=e.src;return xt.fileApi&&!e.hasAttribute("data-mce-bogus")&&!e.hasAttribute("data-mce-placeholder")&&t&&t!==xt.transparentSrc&&(0===t.indexOf("blob:")?!r.isUploaded(t)&&n(e):0===t.indexOf("data:")&&n(e))}),function(f){if(void 0!==o[f.src])return new _r(function(t){o[f.src].then(function(e){return"string"==typeof e?e:void t({image:f,blobInfo:e.blobInfo})})});var e=new _r(function(e,t){var r,o,i,n,a,u,s,c,l;r=d,i=e,n=t,0!==(o=f).src.indexOf("blob:")?(u=(a=zh(o.src)).data,s=a.type,c=u,(l=r.getByData(c,s))?i({image:o,blobInfo:l}):jh(o.src).then(function(e){l=r.create(Vh(),e,c),r.add(l),i({image:o,blobInfo:l})},function(e){n(e)})):(l=r.getByUri(o.src))?i({image:o,blobInfo:l}):jh(o.src).then(function(t){var n=t;new _r(function(e){var t=new FileReader;t.onloadend=function(){e(t.result)},t.readAsDataURL(n)}).then(function(e){c=zh(e).data,l=r.create(Vh(),t,c),r.add(l),i({image:o,blobInfo:l})})},function(e){n(e)})}).then(function(e){return delete o[e.image.src],e}).catch(function(e){return delete o[f.src],e});return o[f.src]=e});return _r.all(t)}}}function $h(e,t){return e.replace(t.re,function(e){return ue(t.uris,e).getOr(e)})}function Wh(e,t,n,r){(e.padd_empty_with_br||t.insert)&&n[r.name]?r.empty().append(new jd("br",1)).shortEnded=!0:r.empty().append(new jd("#text",3)).value=wo}function Kh(n,e,t,r){return r.isEmpty(e,t,function(e){return(t=n.getElementRule(e.name))&&t.paddEmpty;var t})}function Xh(e,p){var t,o,i,h=e.schema;function n(t){var e,n,r=t.attr("src");(e=t).attr("src")===xt.transparentSrc||V(e.attr("data-mce-placeholder"))||V(t.attr("data-mce-bogus"))||((n=/data:([^;]+);base64,([a-z0-9\+\/=\s]+)/i.exec(r))?ve.some({type:n[1],data:decodeURIComponent(n[2])}):ve.none()).filter(function(){return function(e,t){if(t.images_dataimg_filter){var n=new Image;return n.src=e.attr("src"),ne(e.attributes.map,function(e,t){n.setAttribute(t,e)}),t.images_dataimg_filter(n)}return!0}(t,o)}).bind(function(e){var t=e.type,n=e.data;return ve.from(i.getByData(n,t)).orThunk(function(){return Hh(t,n).map(function(e){var t=i.create(Vh(),e,n);return i.add(t),t})})}).each(function(e){t.attr("src",e.blobUri())})}p.remove_trailing_brs&&e.addNodeFilter("br",function(e,t,n){var r,o,i,a,u,s,c,l,f=e.length,d=Nt.extend({},h.getBlockElements()),m=h.getNonEmptyElements(),g=h.getWhiteSpaceElements();for(d.body=1,r=0;r<f;r++)if(i=(o=e[r]).parent,d[o.parent.name]&&o===i.lastChild){for(u=o.prev;u;){if("span"!==(s=u.name)||"bookmark"!==u.attr("data-mce-type")){"br"===s&&(o=null);break}u=u.prev}o&&(o.remove(),Kh(h,m,g,i)&&(c=h.getElementRule(i.name))&&(c.removeEmpty?i.remove():c.paddEmpty&&Wh(p,n,d,i)))}else{for(a=o;i&&i.firstChild===a&&i.lastChild===a&&!d[(a=i).name];)i=i.parent;a===i&&!0!==p.padd_empty_with_br&&((l=new jd("#text",3)).value=wo,o.replace(l))}}),e.addAttributeFilter("href",function(e){var t,n,r=e.length;if(!p.allow_unsafe_link_target)for(;r--;){var o=e[r];"a"===o.name&&"_blank"===o.attr("target")&&o.attr("rel",(n=void 0,n=(t=o.attr("rel"))?Nt.trim(t):"",/\b(noopener)\b/g.test(n)?n:n.split(" ").filter(function(e){return 0<e.length}).concat(["noopener"]).sort().join(" ")))}}),p.allow_html_in_named_anchor||e.addAttributeFilter("id,name",function(e){for(var t,n,r,o,i=e.length;i--;)if("a"===(o=e[i]).name&&o.firstChild&&!o.attr("href"))for(r=o.parent,t=o.lastChild;n=t.prev,r.insert(t,o),t=n;);}),p.fix_list_elements&&e.addNodeFilter("ul,ol",function(e){for(var t,n,r,o=e.length;o--;)"ul"!==(r=(n=e[o]).parent).name&&"ol"!==r.name||(n.prev&&"li"===n.prev.name?n.prev.append(n):((t=new jd("li",1)).attr("style","list-style-type: none"),n.wrap(t)))}),p.validate&&h.getValidClasses()&&e.addAttributeFilter("class",function(e){for(var t=h.getValidClasses(),n=e.length;n--;){for(var r=e[n],o=r.attr("class").split(" "),i="",a=0;a<o.length;a++){var u=o[a],s=!1,c=t["*"];c&&c[u]&&(s=!0),c=t[r.name],(s=!(s||!c||!c[u])||s)&&(i&&(i+=" "),i+=u)}i.length||(i=null),r.attr("class",i)}}),t=e,(i=(o=p).blob_cache)&&t.addAttributeFilter("src",function(e){return Y(e,n)})}var Yh=0,Gh=function(e,t){return e&&e.firstChild&&e.firstChild===e.lastChild&&e.firstChild.name===t},Jh=Nt.each,Qh=Nt.trim,Zh="source protocol authority userInfo user password host port relative path directory file query anchor".split(" "),ev={ftp:21,http:80,https:443,mailto:25},tv=["img","video"],nv=(rv.parseDataUri=function(e){var t,n=decodeURIComponent(e).split(","),r=/data:([^;]+)/.exec(n[0]);return{type:t=r?r[1]:t,data:n[1]}},rv.isDomSafe=function(e,t,n){if((n=void 0===n?{}:n).allow_script_urls)return!0;var r,o,i,a,u=Zo.decode(e).replace(/[\s\u0000-\u001F]+/g,"");try{u=decodeURIComponent(u)}catch(e){u=unescape(u)}return!(/((java|vb)script|mhtml):/i.test(u)||(o=u,i=t,!(r=n).allow_html_data_urls&&(/^data:image\//i.test(o)?(V(a=r.allow_svg_data_urls)?!a:!V(i)||!T(tv,i))&&/^data:image\/svg\+xml/i.test(o):/^data:/i.test(o))))},rv.getDocumentBaseUrl=function(e){var t=0!==e.protocol.indexOf("http")&&"file:"!==e.protocol?e.href:e.protocol+"//"+e.host+e.pathname;return/^[^:]+:\/\/\/?[^\/]+\//.test(t)&&(t=t.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(t)||(t+="/")),t},rv.prototype.setPath=function(e){var t=/^(.*?)\/?(\w+)?$/.exec(e);this.path=t[0],this.directory=t[1],this.file=t[2],this.source="",this.getURI()},rv.prototype.toRelative=function(e){var t;if("./"===e)return e;var n=new rv(e,{base_uri:this});if("mce_host"!==n.host&&this.host!==n.host&&n.host||this.port!==n.port||this.protocol!==n.protocol&&""!==n.protocol)return n.getURI();var r=this.getURI(),o=n.getURI();return r===o||"/"===r.charAt(r.length-1)&&r.substr(0,r.length-1)===o?r:(t=this.toRelPath(this.path,n.path),n.query&&(t+="?"+n.query),n.anchor&&(t+="#"+n.anchor),t)},rv.prototype.toAbsolute=function(e,t){var n=new rv(e,{base_uri:this});return n.getURI(t&&this.isSameOrigin(n))},rv.prototype.isSameOrigin=function(e){if(this.host==e.host&&this.protocol==e.protocol){if(this.port==e.port)return!0;var t=ev[this.protocol];if(t&&(this.port||t)==(e.port||t))return!0}return!1},rv.prototype.toRelPath=function(e,t){var n,r,o=0,i="",a=e.substring(0,e.lastIndexOf("/")).split("/"),u=t.split("/");if(a.length>=u.length)for(n=0,r=a.length;n<r;n++)if(n>=u.length||a[n]!==u[n]){o=n+1;break}if(a.length<u.length)for(n=0,r=u.length;n<r;n++)if(n>=a.length||a[n]!==u[n]){o=n+1;break}if(1===o)return t;for(n=0,r=a.length-(o-1);n<r;n++)i+="../";for(n=o-1,r=u.length;n<r;n++)i+=n!==o-1?"/"+u[n]:u[n];return i},rv.prototype.toAbsPath=function(e,t){var n,r,o=0,i=[],a=/\/$/.test(t)?"/":"",u=e.split("/"),s=t.split("/");for(Jh(u,function(e){e&&i.push(e)}),u=i,n=s.length-1,i=[];0<=n;n--)0!==s[n].length&&"."!==s[n]&&(".."!==s[n]?0<o?o--:i.push(s[n]):o++);return 0!==(r=(n=u.length-o)<=0?q(i).join("/"):u.slice(0,n).join("/")+"/"+q(i).join("/")).indexOf("/")&&(r="/"+r),a&&r.lastIndexOf("/")!==r.length-1&&(r+=a),r},rv.prototype.getURI=function(e){var t;return void 0===e&&(e=!1),this.source&&!e||(t="",e||(this.protocol?t+=this.protocol+"://":t+="//",this.userInfo&&(t+=this.userInfo+"@"),this.host&&(t+=this.host),this.port&&(t+=":"+this.port)),this.path&&(t+=this.path),this.query&&(t+="?"+this.query),this.anchor&&(t+="#"+this.anchor),this.source=t),this.source},rv);function rv(e,t){e=Qh(e),this.settings=t||{};var n,r,o,i,a=this.settings.base_uri,u=this;/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)?u.source=e:(n=0===e.indexOf("//"),0!==e.indexOf("/")||n||(e=(a&&a.protocol||"http")+"://mce_host"+e),/^[\w\-]*:?\/\//.test(e)||(r=this.settings.base_uri?this.settings.base_uri.path:new rv(document.location.href).directory,e=this.settings.base_uri&&""==this.settings.base_uri.protocol?"//mce_host"+u.toAbsPath(r,e):(o=/([^#?]*)([#?]?.*)/.exec(e),(a&&a.protocol||"http")+"://mce_host"+u.toAbsPath(r,o[1])+o[2])),e=e.replace(/@@/g,"(mce_at)"),i=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?(\[[a-zA-Z0-9:.%]+\]|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e),Jh(Zh,function(e,t){var n=(n=i[t])&&n.replace(/\(mce_at\)/g,"@@");u[e]=n}),a&&(u.protocol||(u.protocol=a.protocol),u.userInfo||(u.userInfo=a.userInfo),u.port||"mce_host"!==u.host||(u.port=a.port),u.host&&"mce_host"!==u.host||(u.host=a.host),u.source=""),n&&(u.protocol=""))}function ov(e,t,n){for(var r=/<([!?\/])?([A-Za-z0-9\-_:.]+)/g,o=/(?:\s(?:[^'">]+(?:"[^"]*"|'[^']*'))*[^"'>]*(?:"[^">]*|'[^'>]*)?|\s*|\/)>/g,i=e.getShortEndedElements(),a=1,u=n;0!==a;)for(r.lastIndex=u;;){var s=r.exec(t);if(null===s)return u;if("!"===s[1]){u=Ge(s[2],"--")?sv(t,!1,s.index+"!--".length):sv(t,!0,s.index+1);break}o.lastIndex=r.lastIndex;var c=o.exec(t);if(!l(c)&&c.index===r.lastIndex){"/"===s[1]?--a:Ee(i,s[2])||(a+=1),u=r.lastIndex+c[0].length;break}}return u}function iv(q,$){void 0===$&&($=oo()),q=q||{};var W=uv(),K=W.createElement("form");function n(s,e){void 0===e&&(e="html");for(var t,i,n,c,r,o,a,l,u,f,d,m,g,p,h,v,b,y,C,x=s.html,w=0,S=[],N=0,E=Zo.decode,k=Nt.makeMap("src,href,data,background,action,formaction,poster,xlink:href"),_="html"===e?0:1,A=function(e){for(var t,n=S.length;n--&&S[n].name!==e;);if(0<=n){for(t=S.length-1;n<=t;t--)(e=S[t]).valid&&Q(e.name);S.length=n}},R=function(e,t){return G($h(e,s),t)},D=function(e){""!==e&&(">"===e.charAt(0)&&(e=" "+e),q.allow_conditional_comments||"[if"!==e.substr(0,3).toLowerCase()||(e=" "+e),X($h(e,s)))},T=function(e,t){var n=e||"",r=!Ge(n,"--"),o=sv(x,r,t);return e=x.substr(t,o-t),D(r?n+e:e),o+1},O=new RegExp("<(?:(?:!--([\\w\\W]*?)--!?>)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:![Dd][Oo][Cc][Tt][Yy][Pp][Ee]([\\w\\W]*?)>)|(?:!(--)?)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([A-Za-z][A-Za-z0-9\\-_\\:\\.]*)>)|(?:([A-Za-z][A-Za-z0-9\\-_:.]*)(\\s(?:[^'\">]+(?:\"[^\"]*\"|'[^']*'))*[^\"'>]*(?:\"[^\">]*|'[^'>]*)?|\\s*|\\/)>))","g"),B=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g,P=$.getShortEndedElements(),L=q.self_closing_elements||$.getSelfClosingElements(),I=$.getBoolAttrs(),M=q.validate,F=q.remove_internals,U=q.fix_self_closing,z=$.getSpecialElements(),H=x+">";t=O.exec(H);){var j=t[0];if(w<t.index&&R(E(x.substr(w,t.index-w))),i=t[7])A(i=":"===(i=i.toLowerCase()).charAt(0)?i.substr(1):i);else if(i=t[8]){if(t.index+j.length>x.length){R(E(x.substr(t.index))),w=t.index+j.length;continue}u=(i=":"===(i=i.toLowerCase()).charAt(0)?i.substr(1):i)in P,U&&L[i]&&0<S.length&&S[S.length-1].name===i&&A(i);var V=function(e,t){var n=e.exec(t);if(n){var r=n[1],o=n[2];return"string"==typeof r&&"data-mce-bogus"===r.toLowerCase()?o:null}return null}(B,t[9]);if(null!==V){if("all"===V){w=ov($,x,O.lastIndex),O.lastIndex=w;continue}d=!1}if(!M||(f=$.getElementRule(i))){if(d=!0,M&&(p=f.attributes,h=f.attributePatterns),(g=t[9])?((l=-1!==g.indexOf("data-mce-type"))&&F&&(d=!1),(c=[]).map={},g.replace(B,function(e,t,n,r,o){return function(e,t,n,r,o){var i;if(n=$h((t=t.toLowerCase())in I?t:E(n||r||o||""),s),M&&!l&&0==(0===(i=t).indexOf("data-")||0===i.indexOf("aria-"))){var a=p[t];if(!a&&h){for(var u=h.length;u--&&!(a=h[u]).pattern.test(t););-1===u&&(a=null)}if(!a)return;if(a.validValues&&!(n in a.validValues))return}("name"===t||"id"===t)&&e in av&&(n in W||n in K)||k[t]&&!nv.isDomSafe(n,e,q)||l&&(t in k||0===t.indexOf("on"))||(c.map[t]=n,c.push({name:t,value:n}))}(i,t,n,r,o),""})):(c=[]).map={},M&&!l){if(v=f.attributesRequired,b=f.attributesDefault,y=f.attributesForced,f.removeEmptyAttrs&&!c.length&&(d=!1),y)for(r=y.length;r--;)a=(m=y[r]).name,"{$uid}"===(C=m.value)&&(C="mce_"+N++),c.map[a]=C,c.push({name:a,value:C});if(b)for(r=b.length;r--;)(a=(m=b[r]).name)in c.map||("{$uid}"===(C=m.value)&&(C="mce_"+N++),c.map[a]=C,c.push({name:a,value:C}));if(v){for(r=v.length;r--&&!(v[r]in c.map););-1===r&&(d=!1)}if(m=c.map["data-mce-bogus"]){if("all"===m){w=ov($,x,O.lastIndex),O.lastIndex=w;continue}d=!1}}d&&J(i,c,u)}else d=!1;if(n=z[i]){n.lastIndex=w=t.index+j.length,w=(t=n.exec(x))?(d&&(o=x.substr(w,t.index-w)),t.index+t[0].length):(o=x.substr(w),x.length),d&&(0<o.length&&R(o,!0),Q(i)),O.lastIndex=w;continue}u||(g&&g.indexOf("/")===g.length-1?d&&Q(i):S.push({name:i,valid:d}))}else if(i=t[1])D(i);else if(i=t[2]){if(!(1==_||q.preserve_cdata||0<S.length&&$.isValidChild(S[S.length-1].name,"#cdata"))){w=T("",t.index+2),O.lastIndex=w;continue}Y(i)}else if(i=t[3])ee(i);else{if((i=t[4])||"<!"===j){w=T(i,t.index+j.length),O.lastIndex=w;continue}if(i=t[5]){if(1!=_){w=T("?",t.index+2),O.lastIndex=w;continue}Z(i,t[6])}}w=t.index+j.length}for(w<x.length&&R(E(x.substr(w))),r=S.length-1;0<=r;r--)(i=S[r]).valid&&Q(i.name)}!1!==q.fix_self_closing&&(q.fix_self_closing=!0);var X=q.comment||te,Y=q.cdata||te,G=q.text||te,J=q.start||te,Q=q.end||te,Z=q.pi||te,ee=q.doctype||te;return{parse:function(e,t){void 0===t&&(t="html"),n(function(e){for(var t,n=/data:[^;<"'\s]+;base64,([a-z0-9\+\/=\s]+)/gi,r=[],o={},i=wu("img"),a=0,u=0;t=n.exec(e);){var s=t[0],c=i+"_"+u++;o[c]=s,a<t.index&&r.push(e.substr(a,t.index-a)),r.push(c),a=t.index+s.length}var l=new RegExp(i+"_[0-9]+","g");return 0===a?{prefix:i,uris:o,html:e,re:l}:(a<e.length&&r.push(e.substr(a)),{prefix:i,uris:o,html:r.join(""),re:l})}(e),t)}}}var av=Nt.makeMap("button,fieldset,form,iframe,img,image,input,object,output,select,textarea"),uv=Re(function(){return document.implementation.createHTMLDocument("parser")}),sv=function(e,t,n){void 0===n&&(n=0);var r=e.toLowerCase();if(-1!==r.indexOf("[if ",n)&&(u=n,/^\s*\[if [\w\W]+\]>.*<!\[endif\](--!?)?>/.test(r.substr(u)))){var o=r.indexOf("[endif]",n);return r.indexOf(">",o)}if(t){var i=r.indexOf(">",n);return-1!==i?i:r.length}var a=/--!?>/g;a.lastIndex=n;var u,s=a.exec(e);return s?s.index+s[0].length:r.length};function cv(A,R){void 0===R&&(R=oo());var D={},T=[],O={},B={};(A=A||{}).validate=!("validate"in A)||A.validate,A.root_name=A.root_name||"body";function P(e){var t=e.name;t in D&&((r=O[t])?r.push(e):O[t]=[e]);for(var n=T.length;n--;){var r,o=T[n].name;o in e.attributes.map&&((r=B[o])?r.push(e):B[o]=[e])}return e}var e={schema:R,addAttributeFilter:function(e,n){Rv(Dv(e),function(e){for(var t=0;t<T.length;t++)if(T[t].name===e)return void T[t].callbacks.push(n);T.push({name:e,callbacks:[n]})})},getAttributeFilters:function(){return[].concat(T)},addNodeFilter:function(e,n){Rv(Dv(e),function(e){var t=D[e];t||(D[e]=t=[]),t.push(n)})},getNodeFilters:function(){var e,t=[];for(e in D)Ee(D,e)&&t.push({name:e,callbacks:D[e]});return t},filterNode:P,parse:function(e,s){var t,n,r,o,i,c,a,l,f=[];function d(e){for(var t=R.getBlockElements(),n=e.prev;n&&3===n.type;){var r=n.value.replace(w,"");if(0<r.length)return n.value=r,0;var o=n.next;if(o){if(3===o.type&&o.value.length){n=n.prev;continue}if(!t[o.name]&&"script"!==o.name&&"style"!==o.name){n=n.prev;continue}}var i=n.prev;n.remove(),n=i}}s=s||{},O={},B={};function m(e,t){var n,r=new jd(e,t);return e in D&&((n=O[e])?n.push(r):O[e]=[r]),r}var g=Tv(Av("script,style,head,html,body,title,meta,param"),R.getBlockElements()),p=no(R),h=R.getNonEmptyElements(),v=R.children,b=A.validate,u=("forced_root_block"in s?s:A).forced_root_block,y=!1===u?"":!0===u?"p":u,C=R.getWhiteSpaceElements(),x=/^[ \t\r\n]+/,w=/[ \t\r\n]+$/,S=/[ \t\r\n]+/g,N=/^[ \t\r\n]+$/,E=Ee(C,s.context)||Ee(C,A.root_name),k=iv({validate:b,document:A.document,allow_html_data_urls:A.allow_html_data_urls,allow_svg_data_urls:A.allow_svg_data_urls,allow_script_urls:A.allow_script_urls,allow_conditional_comments:A.allow_conditional_comments,preserve_cdata:A.preserve_cdata,self_closing_elements:function(e){var t,n={};for(t in e)"li"!==t&&"p"!==t&&(n[t]=e[t]);return n}(R.getSelfClosingElements()),cdata:function(e){l.append(m("#cdata",4)).value=e},text:function(e,t){var n,r;E||(e=e.replace(S," "),(r=l.lastChild)&&(Ee(g,r.name)||"br"===r.name)&&(e=e.replace(x,""))),0!==e.length&&((n=m("#text",3)).raw=!!t,l.append(n).value=e)},comment:function(e){l.append(m("#comment",8)).value=e},pi:function(e,t){l.append(m(e,7)).value=t,d(l)},doctype:function(e){l.append(m("#doctype",10)).value=e,d(l)},start:function(e,t,n){var r=b?R.getElementRule(e):{};if(r){var o=m(r.outputName||e,1);o.attributes=t,o.shortEnded=n,l.append(o);var i=v[l.name];i&&v[o.name]&&!i[o.name]&&f.push(o);for(var a=T.length;a--;){var u=T[a].name;u in t.map&&((c=B[u])?c.push(o):B[u]=[o])}g[e]&&d(o),n||(l=o),!E&&C[e]&&(E=!0)}},end:function(e){var t,n,r,o,i=b?R.getElementRule(e):{};if(i){if(g[e]&&!E){if((t=l.firstChild)&&3===t.type)if(0<(n=t.value.replace(x,"")).length)t.value=n,t=t.next;else for(r=t.next,t.remove(),t=r;t&&3===t.type;)n=t.value,r=t.next,0!==n.length&&!N.test(n)||(t.remove(),t=r),t=r;if((t=l.lastChild)&&3===t.type)if(0<(n=t.value.replace(w,"")).length)t.value=n,t=t.prev;else for(r=t.prev,t.remove(),t=r;t&&3===t.type;)n=t.value,r=t.prev,0!==n.length&&!N.test(n)||(t.remove(),t=r),t=r}E&&C[e]&&(E=!1);var a=Kh(R,h,C,l),u=l.parent;i.paddInEmptyBlock&&a&&function(){for(var e=l;V(e);){if(e.name in p)return Kh(R,h,C,e);e=e.parent}}()?Wh(A,s,g,l):i.removeEmpty&&a?g[l.name]?l.empty().remove():l.unwrap():i.paddEmpty&&(Gh(o=l,"#text")&&o.firstChild.value===wo||a)&&Wh(A,s,g,l),l=u}}},R),_=l=new jd(s.context||A.root_name,11);if(k.parse(e,s.format),b&&f.length&&(s.context?s.invalid=!0:function(e){for(var t=Av("tr,td,th,tbody,thead,tfoot,table"),n=R.getNonEmptyElements(),r=R.getWhiteSpaceElements(),o=R.getTextBlockElements(),i=R.getSpecialElements(),a=function(e,t){if(void 0===t&&(t=e.parent),i[e.name])e.empty().remove();else{for(var n=0,r=e.children();n<r.length;n++){var o=r[n];R.isValidChild(t.name,o.name)||a(o,t)}e.unwrap()}},u=0;u<e.length;u++){var s,c=e[u],l=void 0,f=void 0;if(c.parent&&!c.fixed)if(o[c.name]&&"li"===c.parent.name){for(var d=c.next;d&&o[d.name];)d.name="li",d.fixed=!0,c.parent.insert(d,c.parent),d=d.next;c.unwrap()}else{for(var m=[c],l=c.parent;l&&!R.isValidChild(l.name,c.name)&&!t[l.name];l=l.parent)m.push(l);if(l&&1<m.length)if(R.isValidChild(l.name,c.name)){m.reverse();for(var g=s=P(m[0].clone()),p=0;p<m.length-1;p++){R.isValidChild(g.name,m[p].name)?(f=P(m[p].clone()),g.append(f)):f=g;for(var h=m[p].firstChild;h&&h!==m[p+1];){var v=h.next;f.append(h),h=v}g=f}Kh(R,n,r,s)?l.insert(c,m[0],!0):(l.insert(s,m[0],!0),l.insert(c,s)),l=m[0],(Kh(R,n,r,l)||Gh(l,"br"))&&l.empty().remove()}else a(c);else c.parent&&("li"!==c.name?R.isValidChild(c.parent.name,"div")&&R.isValidChild("div",c.name)?c.wrap(P(new jd("div",1))):a(c):!(d=c.prev)||"ul"!==d.name&&"ol"!==d.name?!(d=c.next)||"ul"!==d.name&&"ol"!==d.name?c.wrap(P(new jd("ul",1))):d.insert(c,d.firstChild,!0):d.append(c))}}}(f)),y&&("body"===_.name||s.isRootContent)&&function(){function e(e){e&&((t=e.firstChild)&&3===t.type&&(t.value=t.value.replace(x,"")),(t=e.lastChild)&&3===t.type&&(t.value=t.value.replace(w,"")))}var t=_.firstChild,n=null;if(R.isValidChild(_.name,y.toLowerCase())){for(;t;){var r=t.next;3===t.type||1===t.type&&"p"!==t.name&&!g[t.name]&&!t.attr("data-mce-type")?(n||((n=m(y,1)).attr(A.forced_root_block_attrs),_.insert(n,t)),n.append(t)):(e(n),n=null),t=r}e(n)}}(),!s.invalid){for(a in O)if(Ee(O,a)){for(c=D[a],o=(t=O[a]).length;o--;)t[o].parent||t.splice(o,1);for(n=0,r=c.length;n<r;n++)c[n](t,a,s)}for(n=0,r=T.length;n<r;n++)if((c=T[n]).name in B){for(o=(t=B[c.name]).length;o--;)t[o].parent||t.splice(o,1);for(o=0,i=c.callbacks.length;o<i;o++)c.callbacks[o](t,c.name,s)}}return _}};return Xh(e,A),A.inline_styles&&Uh(e,A),e}function lv(e,t,n){-1===Nt.inArray(t,n)&&(e.addAttributeFilter(n,function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),t.push(n))}function fv(L,I){var e=["data-mce-selected"],M=I&&I.dom?I.dom:eu.DOM,F=I&&I.schema?I.schema:oo(L);L.entity_encoding=L.entity_encoding||"named",L.remove_trailing_brs=!("remove_trailing_brs"in L)||L.remove_trailing_brs;var t,U=cv(L,F),s=L,c=M;return(t=U).addAttributeFilter("data-mce-tabindex",function(e,t){for(var n=e.length;n--;){var r=e[n];r.attr("tabindex",r.attr("data-mce-tabindex")),r.attr(t,null)}}),t.addAttributeFilter("src,href,style",function(e,t){for(var n="data-mce-"+t,r=s.url_converter,o=s.url_converter_scope,i=e.length;i--;){var a=e[i],u=a.attr(n);void 0!==u?(a.attr(t,0<u.length?u:null),a.attr(n,null)):(u=a.attr(t),"style"===t?u=c.serializeStyle(c.parseStyle(u),a.name):r&&(u=r.call(o,u,t,a.name)),a.attr(t,0<u.length?u:null))}}),t.addAttributeFilter("class",function(e){for(var t=e.length;t--;){var n,r=e[t];r.attr("class")&&(n=r.attr("class").replace(/(?:^|\s)mce-item-\w+(?!\S)/g,""),r.attr("class",0<n.length?n:null))}}),t.addAttributeFilter("data-mce-type",function(e,t,n){for(var r=e.length;r--;){var o=e[r];"bookmark"!==o.attr("data-mce-type")||n.cleanup||(ve.from(o.firstChild).exists(function(e){return!No(e.value)})?o.unwrap():o.remove())}}),t.addNodeFilter("noscript",function(e){for(var t=e.length;t--;){var n=e[t].firstChild;n&&(n.value=Zo.decode(n.value))}}),t.addNodeFilter("script,style",function(e,t){for(var n=function(e){return e.replace(/(<!--\[CDATA\[|\]\]-->)/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi,"").replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")},r=e.length;r--;){var o,i=e[r],a=i.firstChild?i.firstChild.value:"";"script"===t?((o=i.attr("type"))&&i.attr("type","mce-no/type"===o?null:o.replace(/^mce\-/,"")),"xhtml"===s.element_format&&0<a.length&&(i.firstChild.value="// <![CDATA[\n"+n(a)+"\n// ]]>")):"xhtml"===s.element_format&&0<a.length&&(i.firstChild.value="\x3c!--\n"+n(a)+"\n--\x3e")}}),t.addNodeFilter("#comment",function(e){for(var t=e.length;t--;){var n=e[t];s.preserve_cdata&&0===n.value.indexOf("[CDATA[")?(n.name="#cdata",n.type=4,n.value=c.decode(n.value.replace(/^\[CDATA\[|\]\]$/g,""))):0===n.value.indexOf("mce:protected ")&&(n.name="#text",n.type=3,n.raw=!0,n.value=unescape(n.value).substr(14))}}),t.addNodeFilter("xml:namespace,input",function(e,t){for(var n=e.length;n--;){var r=e[n];7===r.type?r.remove():1===r.type&&("input"!==t||r.attr("type")||r.attr("type","text"))}}),t.addAttributeFilter("data-mce-type",function(e){Y(e,function(e){"format-caret"===e.attr("data-mce-type")&&(e.isEmpty(t.schema.getNonEmptyElements())?e.remove():e.unwrap())})}),t.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style,data-mce-selected,data-mce-expando,data-mce-type,data-mce-resize,data-mce-placeholder",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),{schema:F,addNodeFilter:U.addNodeFilter,addAttributeFilter:U.addAttributeFilter,serialize:function(e,t){var n,r,o,i,a,u,s,c,l,f,d,m,g,p,h,v,b,y,C,x,w,S,N,E,k,_,A,R,D,T=_e({format:"html"},t=void 0===t?{}:t),O=(n=(m=e,N=g=T,(d=I)&&d.hasEventListeners("PreProcess")&&!N.no_events?(h=g,x=(p=d).dom,w=m.cloneNode(!0),(S=document.implementation).createHTMLDocument&&(b=S.createHTMLDocument(""),Nt.each("BODY"===w.nodeName?w.childNodes:[w],function(e){b.body.appendChild(b.importNode(e,!0))}),w="BODY"!==w.nodeName?b.body.firstChild:b.body,v=x.doc,x.doc=b),y=p,C=_e(_e({},h),{node:w}),y.fire("PreProcess",C),v&&(x.doc=v),w):m),o=Eo((r=T).getInner?n.innerHTML:M.getOuterHTML(n)),r.selection||Co(Et.fromDom(n))?o:Nt.trim(o)),B=(i=U,a=O,s=(u=T).selection?_e({forced_root_block:!1},u):u,c=i.parse(a,s),!P(f=c.lastChild)||P(l=f.prev)&&(f.remove(),l.remove()),c);function P(e){return e&&"br"===e.name}return"tree"===T.format?B:(E=I,k=T,_=B,D=rm(L,F).serialize(_),k.no_events||!E?D:(A=E,R=_e(_e({},k),{content:D}),A.fire("PostProcess",R).content))},addRules:F.addValidElements,setRules:F.setValidElements,addTempAttr:R(lv,U,e),getTempAttrs:J(e),getNodeFilters:U.getNodeFilters,getAttributeFilters:U.getAttributeFilters}}function dv(e,t){var n=fv(e,t);return{schema:n.schema,addNodeFilter:n.addNodeFilter,addAttributeFilter:n.addAttributeFilter,serialize:n.serialize,addRules:n.addRules,setRules:n.setRules,addTempAttr:n.addTempAttr,getTempAttrs:n.getTempAttrs,getNodeFilters:n.getNodeFilters,getAttributeFilters:n.getAttributeFilters}}function mv(e,t,n){return r=n=void 0===n?{}:n,bh(e).editor.setContent(t,r);var r}function gv(e){return ve.from(e).each(function(e){return e.destroy()})}function pv(e,t){var n,r,o,i,a,u,s,c=(n=e,r=U(Pv,function(e){return Ee(n,e)}),!1!==(o=n.forced_root_block)&&""!==o||r.push("forced_root_block (false only)"),W(r)),l=(s=Nt.makeMap(t.plugins," "),W(Ae(Ae([],U(Lv,g),!0),H(Iv,function(e){return g(e)?[e+" (moving to premium)"]:[]}),!0))),f=0<l.length,d=0<c.length,m="mobile"===t.theme;function g(e){return Ee(s,e)}(f||d||m)&&(i=m?"\n\nThemes:\n- mobile":"",a=f?"\n\nPlugins:\n- "+l.join("\n- "):"",u=d?"\n\nSettings:\n- "+c.join("\n- "):"",console.warn("The following deprecated features are currently enabled, these will be removed in TinyMCE 6.0. See https://www.tiny.cloud/docs/release-notes/6.0-upcoming-changes/ for more information."+i+a+u))}function hv(e){var t=S(e)?e.join(" "):e;return U(A(X(t)?t.split(" "):[],Je),function(e){return 0<e.length})}function vv(e,t){return Ee(e.sections(),t)}function bv(e,t){return ue(e,"toolbar_mode").orThunk(function(){return ue(e,"toolbar_drawer").map(function(e){return!1===e?"wrap":e})}).getOr(t)}function yv(e,t,n,r){var o,i,a,u,s,c,l,f,d=hv(n.forced_plugins),m=hv(r.plugins),g=vv(o=t,"mobile")?o.sections().mobile:{},p=g.plugins?hv(g.plugins):m,h=(i=(u=t,s=m,c=p,(a=e)&&(0,f=(l=u).sections(),vv(l,"mobile")&&"mobile"===f.mobile.theme)?U(c,R(T,Hv)):a&&vv(u,"mobile")?c:s),[].concat(hv(d)).concat(hv(i)));if(xt.browser.isIE()&&T(h,"rtc"))throw new Error("RTC plugin is not supported on IE 11.");return Nt.extend(r,{plugins:h.join(" ")})}function Cv(e,t,n,r,o){var i,a,u,s,c,l,f,d,m=e?{mobile:(i=t,a={resize:!1,toolbar_mode:bv(o.mobile||{},"scrolling"),toolbar_sticky:!1},_e(_e(_e({},jv),a),i?{menubar:!1}:{}))}:{},g=(c=["mobile"],ie(Bv(m,o),function(e,t){return T(c,t)},oe(l={}),oe(f={})),{sections:J((d={t:l,f:f}).t),settings:J(d.f)}),p=Nt.extend(n,r,g.settings(),e&&vv(g,"mobile")?function(e){void 0===e&&(e={});var t=ue(g.sections(),"mobile").getOr({});return Nt.extend({},e,t)}():{},{validate:!0,external_plugins:(u=r,s=g.settings().external_plugins||{},u&&u.external_plugins?Nt.extend({},u.external_plugins,s):s)});return yv(e,g,r,p)}function xv(e,t,n){return ve.from(t.settings[n]).filter(e)}function wv(e,t){return t.dom[e]}function Sv(e,t){return parseInt(wn(t,e),10)}function Nv(e,t,n){var r,o,i,a,u,s,c=Et.fromDom(e.getBody()),l=e.inline?c:Et.fromDom(Dt(c).dom.documentElement),f=(r=e.inline,i=t,a=n,u=(o=l).dom.getBoundingClientRect(),{x:i-(r?u.left+o.dom.clientLeft+Kv(o):0),y:a-(r?u.top+o.dom.clientTop+Wv(o):0)}),d=f.x,m=f.y,g=qv(s=l),p=$v(s);return 0<=d&&0<=m&&d<=g&&m<=p}function Ev(o){function i(){var e=o.theme;return e&&e.getNotificationManagerImpl?e.getNotificationManagerImpl():{open:t,close:t,reposition:t,getArgs:t};function t(){throw new Error("Theme did not provide a NotificationManager implementation.")}}function a(){return ve.from(c[0])}function u(){0<c.length&&i().reposition(c)}function s(t){z(c,function(e){return e===t}).each(function(e){c.splice(e,1)})}function t(n,e){if(void 0===e&&(e=!0),!o.removed&&(r=(t=o).inline?t.getBody():t.getContentAreaContainer(),ve.from(r).map(Et.fromDom).map(Mn).getOr(!1)))return e&&o.fire("BeforeOpenNotification",{notification:n}),M(c,function(e){return!((t=i().getArgs(e)).type!==n.type||t.text!==n.text||t.progressBar||t.timeout||n.progressBar||n.timeout);var t}).getOrThunk(function(){o.editorManager.setActive(o);var e=i().open(n,function(){s(e),u(),a().fold(function(){return o.focus()},function(e){return Et.fromDom(e.getEl()).dom.focus()})});return c.push(e),u(),o.fire("OpenNotification",{notification:_e({},e)}),e});var t,r}var n,c=[],e=J(c);return(n=o).on("SkinLoaded",function(){var e=n.getParam("service_message");e&&t({text:e,type:"warning",timeout:0},!1),u()}),n.on("show ResizeEditor ResizeWindow NodeChange",function(){Ar.requestAnimationFrame(u)}),n.on("remove",function(){Y(c.slice(),function(e){i().close(e)})}),{open:t,close:function(){a().each(function(e){i().close(e),s(e),u()})},getNotifications:e}}iv.findEndTag=ov;var kv,_v,Av=Nt.makeMap,Rv=Nt.each,Dv=Nt.explode,Tv=Nt.extend,Ov=eu.DOM,Bv=(kv=function(e,t){return h(e)&&h(t)?Bv(e,t):t},function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];if(0===e.length)throw new Error("Can't merge zero objects");for(var n={},r=0;r<e.length;r++){var o,i=e[r];for(o in i)Ee(i,o)&&(n[o]=kv(n[o],i[o]))}return n}),Pv="autoresize_on_init,content_editable_state,convert_fonts_to_spans,inline_styles,padd_empty_with_br,block_elements,boolean_attributes,editor_deselector,editor_selector,elements,file_browser_callback_types,filepicker_validator_handler,force_hex_style_colors,force_p_newlines,gecko_spellcheck,images_dataimg_filter,media_scripts,mode,move_caret_before_on_enter_elements,non_empty_elements,self_closing_elements,short_ended_elements,special,spellchecker_select_languages,spellchecker_whitelist,tab_focus,table_responsive_width,text_block_elements,text_inline_elements,toolbar_drawer,types,validate,whitespace_elements,paste_word_valid_elements,paste_retain_style_properties,paste_convert_word_fake_lists".split(","),Lv="bbcode,colorpicker,contextmenu,fullpage,legacyoutput,spellchecker,textcolor".split(","),Iv="imagetools,toc".split(","),Mv=dt().deviceType,Fv=Mv.isTouch(),Uv=Mv.isPhone(),zv=Mv.isTablet(),Hv=["lists","autolink","autosave"],jv={table_grid:!1,object_resizing:!1,resize:!1},Vv=(_v={},{add:function(e,t){_v[e]=t},get:function(e){return _v[e]||{icons:{}}},has:function(e){return Ee(_v,e)}}),qv=R(wv,"clientWidth"),$v=R(wv,"clientHeight"),Wv=R(Sv,"margin-top"),Kv=R(Sv,"margin-left"),Xv=fu.PluginManager,Yv=fu.ThemeManager;function Gv(r){function o(){var e=r.theme;return e&&e.getWindowManagerImpl?e.getWindowManagerImpl():{open:t,openUrl:t,alert:t,confirm:t,close:t,getParams:t,setParams:t};function t(){throw new Error("Theme did not provide a WindowManager implementation.")}}function i(n,r){return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return r?r.apply(n,e):void 0}}function n(t){r.fire("CloseWindow",{dialog:t}),0===(u=U(u,function(e){return e!==t})).length&&r.focus()}function a(e){r.editorManager.setActive(r),dd(r);var t,n=e();return t=n,u.push(t),r.fire("OpenWindow",{dialog:t}),n}var u=[];return r.on("remove",function(){Y(u,function(e){o().close(e)})}),{open:function(e,t){return a(function(){return o().open(e,t,n)})},openUrl:function(e){return a(function(){return o().openUrl(e,n)})},alert:function(e,t,n){var r=o();r.alert(e,i(n||r,t))},confirm:function(e,t,n){var r=o();r.confirm(e,i(n||r,t))},close:function(){ve.from(u[u.length-1]).each(function(e){o().close(e),n(e)})}}}function Jv(e,t){e.notificationManager.open({type:"error",text:t})}function Qv(e,t){e._skinLoaded?Jv(e,t):e.on("SkinLoaded",function(){Jv(e,t)})}function Zv(e,t,n){Cf(e,t,{message:n}),console.error(n)}function eb(e,t,n){return n?"Failed to load "+e+": "+n+" from url "+t:"Failed to load "+e+" url: "+t}function tb(e,t,n){Zv(e,"PluginLoadError",eb("plugin",t,n))}function nb(e){var t,n;e.contentCSS=e.contentCSS.concat(Ey(e,(n=(t=e).getParam("content_css"),X(n)?A(n.split(","),Je):S(n)?n:!1===n||t.inline?[]:["default"])),Ey(e,Bs(e)))}function rb(){function n(e,t){return{status:e,resultUri:t}}function t(e){return e in r}var r={};return{hasBlobUri:t,getResultUri:function(e){var t=r[e];return t?t.resultUri:null},isPending:function(e){return!!t(e)&&1===r[e].status},isUploaded:function(e){return!!t(e)&&2===r[e].status},markPending:function(e){r[e]=n(1,null)},markUploaded:function(e,t){r[e]=n(2,t)},removeFailed:function(e){delete r[e]},destroy:function(){r={}}}}function ob(e){return e+ky+++("s"+(new Date).getTime().toString(36)+t()+t()+t());function t(){return Math.round(4294967295*Math.random()).toString(36)}}function ib(){function e(e){return M(n,e).getOrUndefined()}function i(e){if(!e.blob||!e.base64)throw new Error("blob and base64 representations of the image are required for BlobInfo to be created");var t=e.id||ob("blobid"),n=e.name||t,r=e.blob;return{id:J(t),name:J(n),filename:J(e.filename||n+"."+({"image/jpeg":"jpg","image/jpg":"jpg","image/gif":"gif","image/png":"png","image/apng":"apng","image/avif":"avif","image/svg+xml":"svg","image/webp":"webp","image/bmp":"bmp","image/tiff":"tiff"}[r.type.toLowerCase()]||"dat")),blob:J(r),base64:J(e.base64),blobUri:J(e.blobUri||URL.createObjectURL(r)),uri:J(e.uri)}}function t(t){return e(function(e){return e.id()===t})}var n=[];return{create:function(e,t,n,r,o){if(X(e))return i({id:e,name:r,filename:o,blob:t,base64:n});if(h(e))return i(e);throw new Error("Unknown input type")},add:function(e){t(e.id())||n.push(e)},get:t,getByUri:function(t){return e(function(e){return e.blobUri()===t})},getByData:function(t,n){return e(function(e){return e.base64()===t&&e.blob().type===n})},findFirst:e,removeByUri:function(t){n=U(n,function(e){return e.blobUri()!==t||void URL.revokeObjectURL(e.blobUri())})},destroy:function(){Y(n,function(e){URL.revokeObjectURL(e.blobUri())}),n=[]}}}function ab(u,s){function o(e,r,o,t){var i=new XMLHttpRequest;i.open("POST",s.url),i.withCredentials=s.credentials,i.upload.onprogress=function(e){t(e.loaded/e.total*100)},i.onerror=function(){o("Image upload failed due to a XHR Transport error. Code: "+i.status)},i.onload=function(){var e,t,n;i.status<200||300<=i.status?o("HTTP Error: "+i.status):(e=JSON.parse(i.responseText))&&"string"==typeof e.location?r((t=s.basePath,n=e.location,t?t.replace(/\/$/,"")+"/"+n.replace(/^\//,""):n)):o("Invalid JSON: "+i.responseText)};var n=new FormData;n.append("file",e.blob(),e.filename()),i.send(n)}function c(e,t){return{url:t,blobInfo:e,status:!0}}function l(e,t,n){return{url:"",blobInfo:e,status:!1,error:{message:t,options:n}}}function f(e,t){Nt.each(d[e],function(e){e(t)}),delete d[e]}var d={};return!1===y(s.handler)&&(s.handler=o),{upload:function(e,t){return s.url||s.handler!==o?(n=e,r=t,n=Nt.grep(e,function(e){return!u.isUploaded(e.blobUri())}),_r.all(Nt.map(n,function(e){return u.isPending(e.blobUri())?(n=e.blobUri(),new _r(function(e){d[n]=d[n]||[],d[n].push(e)})):(i=e,t=s.handler,a=r,u.markPending(i.blobUri()),new _r(function(r){var n;try{var o=function(){n&&n.close()};t(i,function(e){o(),u.markUploaded(i.blobUri(),e),f(i.blobUri(),c(i,e)),r(c(i,e))},function(e,t){var n=t||{};o(),u.removeFailed(i.blobUri()),f(i.blobUri(),l(i,e,n)),r(l(i,e,n))},function(t){t<0||100<t||ve.from(n).orThunk(function(){return ve.from(a).map(C)}).each(function(e){(n=e).progressBar.value(t)})})}catch(e){r(l(i,e.message,{}))}}));var i,t,a,n}))):new _r(function(e){e([])});var n,r}}}function ub(e){return function(){return e.notificationManager.open({text:e.translate("Image uploading..."),type:"info",timeout:-1,progressBar:!0})}}function sb(e,t){return ab(t,{url:e.getParam("images_upload_url","","string"),basePath:e.getParam("images_upload_base_path","","string"),credentials:e.getParam("images_upload_credentials",!1,"boolean"),handler:e.getParam("images_upload_handler",null,"function")})}function cb(l){function t(t){return function(e){return l.selection?t(e):[]}}function r(e,t,n){for(var r=0;-1!==(r=e.indexOf(t,r))&&(e=e.substring(0,r)+n+e.substr(r+t.length),r+=n.length-t.length+1),-1!==r;);return e}function o(e,t,n){return e=r(e,'src="'+t+'"','src="'+n+'"'+(n===xt.transparentSrc?' data-mce-placeholder="1"':"")),r(e,'data-mce-src="'+t+'"','data-mce-src="'+n+'"')}function f(t,n){Y(l.undoManager.data,function(e){"fragmented"===e.type?e.fragments=A(e.fragments,function(e){return o(e,t,n)}):e.content=o(e.content,t,n)})}function n(n){return u=u||sb(l,g),v().then(t(function(c){var e=A(c,function(e){return e.blobInfo});return u.upload(e,ub(l)).then(t(function(e){var s=[],t=A(e,function(e,t){var n,r,o,i,a=c[t].blobInfo,u=c[t].image;return e.status&&l.getParam("images_replace_blob_uris",!0,"boolean")?(m.removeByUri(u.src),hh(l)||(r=u,o=e.url,i=l.convertURL(o,"src"),f(r.src,o),l.$(r).attr({src:l.getParam("images_reuse_filename",!1,"boolean")?o+(-1===o.indexOf("?")?"?":"&")+(new Date).getTime():o,"data-mce-src":i}))):e.error&&(e.error.options.remove&&(f(u.getAttribute("src"),xt.transparentSrc),s.push(u)),n=e.error.message,Qv(l,lu.translate(["Failed to upload image: {0}",n]))),{element:u,status:e.status,uploadUri:e.url,blobInfo:a}});return 0<t.length&&h.fireIfChanged(),0<s.length&&(hh(l)?console.error("Removing images on failed uploads is currently unsupported for RTC"):l.undoManager.transact(function(){Y(s,function(e){l.dom.remove(e),m.removeByUri(e.src)})})),n&&n(t),t}))}))}function e(e){if(As(l))return n(e)}function i(t){return!1!==j(p,function(e){return e(t)})&&(0!==t.getAttribute("src").indexOf("data:")||l.getParam("images_dataimg_filter",w,"function")(t))}function a(e){return e.replace(/src="(blob:[^"]+)"/g,function(e,n){var t=g.getResultUri(n);if(t)return'src="'+t+'"';var r=(r=m.getByUri(n))||L(l.editorManager.get(),function(e,t){return e||t.editorUpload&&t.editorUpload.blobCache.getByUri(n)},null);return r?'src="data:'+r.blob().type+";base64,"+r.base64()+'"':e})}var u,s,c,d,m=ib(),g=rb(),p=[],h=(d=au(null),(c=l).on("change AddUndo",function(e){d.set(_e({},e.level))}),{fireIfChanged:function(){var t=c.undoManager.data;Z(t).filter(function(e){return!fh(d.get(),e)}).each(function(e){c.setDirty(!0),c.fire("change",{level:e,lastLevel:G(t,t.length-2).getOrNull()})})}}),v=function(){return(s=s||qh(g,m)).findAll(l.getBody(),i).then(t(function(e){return e=U(e,function(e){return"string"!=typeof e||void Qv(l,e)}),hh(l)||Y(e,function(e){f(e.image.src,e.blobInfo.blobUri()),e.image.src=e.blobInfo.blobUri(),e.image.removeAttribute("data-mce-src")}),e}))};return l.on("SetContent",function(){(As(l)?e:v)()}),l.on("RawSaveContent",function(e){e.content=a(e.content)}),l.on("GetContent",function(e){e.source_view||"raw"===e.format||"tree"===e.format||(e.content=a(e.content))}),l.on("PostRender",function(){l.parser.addNodeFilter("img",function(e){Y(e,function(e){var t,n=e.attr("src");m.getByUri(n)||(t=g.getResultUri(n))&&e.attr("src",t)})})}),{blobCache:m,addFilter:function(e){p.push(e)},uploadImages:n,uploadImagesAuto:e,scanForImages:v,destroy:function(){m.destroy(),g.destroy(),s=u=null}}}function lb(e,t){function m(e){o="string"==typeof e?{name:e,classes:[],attrs:{}}:e;var t,n=Ay.create(o.name),r=n;return(t=o).classes.length&&Ay.addClass(r,t.classes.join(" ")),Ay.setAttribs(r,t.attrs),n}var n,o,r,g=t&&t.schema||oo({}),p=function(n,e,t){var r,o,i,a,u,s,c,l=0<e.length&&e[0],f=l&&l.name,d=(a=f,u="string"!=typeof(i=n)?i.nodeName.toLowerCase():i,!(!(c=(s=g.getElementRule(u))&&s.parentsRequired)||!c.length)&&(a&&-1!==Nt.inArray(c,a)?a:c[0]));if(d)f===d?(o=e[0],e=e.slice(1)):o=d;else if(l)o=e[0],e=e.slice(1);else if(!t)return n;return o&&(r=m(o)).appendChild(n),t&&(r||(r=Ay.create("div")).appendChild(n),Nt.each(t,function(e){var t=m(e);r.insertBefore(t,n)})),p(r,e,o&&o.siblings)};return e&&e.length?(n=m(o=e[0]),(r=Ay.create("div")).appendChild(p(n,e.slice(1),o.siblings)),r):""}function fb(e){var t,a={classes:[],attrs:{}};return"*"!==(e=a.selector=Nt.trim(e))&&(t=e.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g,function(e,t,n,r,o){switch(t){case"#":a.attrs.id=n;break;case".":a.classes.push(n);break;case":":-1!==Nt.inArray("checked disabled enabled read-only required".split(" "),n)&&(a.attrs[n]=n)}var i;return"["!==r||(i=o.match(/([\w\-]+)(?:\=\"([^\"]+))?/))&&(a.attrs[i[1]]=i[2]),""})),a.name=t||"div",a}function db(n,e){var r,t,o="",i=(t=n.getParam("preview_styles","font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow"),X(t)?t:"");if(""===i)return"";function a(e){return e.replace(/%(\w+)/g,"")}if("string"==typeof e){if(!(e=n.formatter.get(e)))return;e=e[0]}if("preview"in e){var u=ue(e,"preview");if(fn(u,!1))return"";i=u.getOr(i)}var s,c=e.block||e.inline||"span",l=(s=e.selector)&&"string"==typeof s?(s=(s=s.split(/\s*,\s*/)[0]).replace(/\s*(~\+|~|\+|>)\s*/g,"$1"),Nt.map(s.split(/(?:>|\s+(?![^\[\]]+\]))/),function(e){var t=Nt.map(e.split(/(?:~\+|~|\+)/),fb),n=t.pop();return t.length&&(n.siblings=t),n}).reverse()):[],f=l.length?(l[0].name||(l[0].name=c),c=e.selector,lb(l,n)):lb([c],n),d=Ay.select(c,f)[0]||f.firstChild;return _y(e.styles,function(e,t){var n=a(e);n&&Ay.setStyle(d,t,n)}),_y(e.attributes,function(e,t){var n=a(e);n&&Ay.setAttrib(d,t,n)}),_y(e.classes,function(e){var t=a(e);Ay.hasClass(d,t)||Ay.addClass(d,t)}),n.fire("PreviewFormats"),Ay.setStyles(f,{position:"absolute",left:-65535}),n.getBody().appendChild(f),r=Ay.getStyle(n.getBody(),"fontSize",!0),r=/px$/.test(r)?parseInt(r,10):0,_y(i.split(" "),function(e){var t=Ay.getStyle(d,e,!0);if(!("background-color"===e&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(t)&&(t=Ay.getStyle(n.getBody(),e,!0),"#ffffff"===Ay.toHex(t).toLowerCase())||"color"===e&&"#000000"===Ay.toHex(t).toLowerCase())){if("font-size"===e&&/em|%$/.test(t)){if(0===r)return;t=parseFloat(t)/(/%$/.test(t)?100:1)*r+"px"}"border"===e&&t&&(o+="padding:0 2px;"),o+=e+":"+t+";"}}),n.fire("AfterPreviewFormats"),Ay.remove(f),o}function mb(c){var e,r,t,n,o,i,a=(n={},(o=function(e,t){e&&(X(e)?(Y(t=!S(t)?[t]:t,function(e){b(e.deep)&&(e.deep=!gl(e)),b(e.split)&&(e.split=!gl(e)||pl(e)),b(e.remove)&&gl(e)&&!pl(e)&&(e.remove="none"),gl(e)&&pl(e)&&(e.mixed=!0,e.block_expand=!0),X(e.classes)&&(e.classes=e.classes.split(/\s+/))}),n[e]=t):ne(e,function(e,t){o(t,e)}))})((r=(e=c).dom,t={valigntop:[{selector:"td,th",styles:{verticalAlign:"top"}}],valignmiddle:[{selector:"td,th",styles:{verticalAlign:"middle"}}],valignbottom:[{selector:"td,th",styles:{verticalAlign:"bottom"}}],alignleft:[{selector:"figure.image",collapsed:!1,classes:"align-left",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"left"},inherit:!1,preview:!1,defaultBlock:"div"},{selector:"img,table,audio,video",collapsed:!1,styles:{float:"left"},preview:"font-family font-size"}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"center"},inherit:!1,preview:"font-family font-size",defaultBlock:"div"},{selector:"figure.image",collapsed:!1,classes:"align-center",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"img,audio,video",collapsed:!1,styles:{display:"block",marginLeft:"auto",marginRight:"auto"},preview:!1},{selector:"table",collapsed:!1,styles:{marginLeft:"auto",marginRight:"auto"},preview:"font-family font-size"}],alignright:[{selector:"figure.image",collapsed:!1,classes:"align-right",ceFalseOverride:!0,preview:"font-family font-size"},{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"right"},inherit:!1,preview:"font-family font-size",defaultBlock:"div"},{selector:"img,table,audio,video",collapsed:!1,styles:{float:"right"},preview:"font-family font-size"}],alignjustify:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li",styles:{textAlign:"justify"},inherit:!1,defaultBlock:"div",preview:"font-family font-size"}],bold:[{inline:"strong",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all",preserve_attributes:["class","style"]}],italic:[{inline:"em",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all",preserve_attributes:["class","style"]}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:!0},{inline:"u",remove:"all",preserve_attributes:["class","style"]}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:!0},{inline:"strike",remove:"all",preserve_attributes:["class","style"]},{inline:"s",remove:"all",preserve_attributes:["class","style"]}],forecolor:{inline:"span",styles:{color:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0},fontname:{inline:"span",toggle:!1,styles:{fontFamily:"%value"},clear_child_styles:!0},fontsize:{inline:"span",toggle:!1,styles:{fontSize:"%value"},clear_child_styles:!0},lineheight:{selector:"h1,h2,h3,h4,h5,h6,p,li,td,th,div",defaultBlock:"p",styles:{lineHeight:"%value"}},fontsize_class:{inline:"span",attributes:{class:"%value"}},blockquote:{block:"blockquote",wrapper:!0,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},code:{inline:"code"},link:{inline:"a",selector:"a",remove:"all",split:!0,deep:!0,onmatch:function(e,t,n){return Hn(e)&&e.hasAttribute("href")},onformat:function(n,e,t){Nt.each(t,function(e,t){r.setAttrib(n,t,e)})}},lang:{inline:"span",clear_child_styles:!0,remove_similar:!0,attributes:{lang:"%value","data-mce-lang":function(e){var t;return null!==(t=null==e?void 0:e.customValue)&&void 0!==t?t:null}}},removeformat:[{selector:"b,strong,em,i,font,u,strike,s,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins,small",remove:"all",split:!0,expand:!1,block_expand:!0,deep:!0},{selector:"span",attributes:["style","class"],remove:"empty",split:!0,expand:!1,deep:!0},{selector:"*",attributes:["style","class"],split:!1,expand:!1,deep:!0}]},Nt.each("p h1 h2 h3 h4 h5 h6 div address pre dt dd samp".split(/\s/),function(e){t[e]={block:e,remove:"all"}}),t)),o(e.getParam("formats")),{get:function(e){return V(e)?n[e]:n},has:function(e){return Ee(n,e)},register:o,unregister:function(e){return e&&n[e]&&delete n[e],n}}),l=au(null);return function(e){e.addShortcut("meta+b","","Bold"),e.addShortcut("meta+i","","Italic"),e.addShortcut("meta+u","","Underline");for(var t=1;t<=6;t++)e.addShortcut("access+"+t,"",["FormatBlock",!1,"h"+t]);e.addShortcut("access+7","",["FormatBlock",!1,"p"]),e.addShortcut("access+8","",["FormatBlock",!1,"div"]),e.addShortcut("access+9","",["FormatBlock",!1,"address"])}(c),(i=c).on("mouseup keydown",function(e){var t=i,n=e.keyCode,r=t.selection,o=t.getBody();Hg(t,null,!1),8!==n&&46!==n||!r.isCollapsed()||r.getStart().innerHTML!==Cp||Hg(t,qc(o,r.getStart())),37!==n&&39!==n||Hg(t,qc(o,r.getStart()))}),{get:a.get,has:a.has,register:a.register,unregister:a.unregister,apply:function(e,t,n){var r=e,o=t,i=n;yh(c).formatter.apply(r,o,i)},remove:function(e,t,n,r){var o=e,i=t,a=n,u=r;yh(c).formatter.remove(o,i,a,u)},toggle:function(e,t,n){var r=e,o=t,i=n;yh(c).formatter.toggle(r,o,i)},match:function(e,t,n,r){return o=e,i=t,a=n,u=r,yh(c).formatter.match(o,i,a,u);var o,i,a,u},closest:function(e){return t=e,yh(c).formatter.closest(t);var t},matchAll:function(e,t){return n=e,r=t,yh(c).formatter.matchAll(n,r);var n,r},matchNode:function(e,t,n,r){return o=e,i=t,a=n,u=r,yh(c).formatter.matchNode(o,i,a,u);var o,i,a,u},canApply:function(e){return t=e,yh(c).formatter.canApply(t);var t},formatChanged:function(e,t,n,r){return o=l,i=e,a=t,u=n,s=r,yh(c).formatter.formatChanged(o,i,a,u,s);var o,i,a,u,s},getCssText:R(db,c)}}function gb(e){switch(e.toLowerCase()){case"undo":case"redo":case"mcerepaint":case"mcefocus":return 1;default:return}}function pb(s){var e,n,r,o,i,c=du(),l=au(0),f=au(0),d={data:[],typing:!1,beforeChange:function(){var e=l,t=c;yh(s).undoManager.beforeChange(e,t)},add:function(e,t){return n=d,r=f,o=l,i=c,a=e,u=t,yh(s).undoManager.add(n,r,o,i,a,u);var n,r,o,i,a,u},undo:function(){return e=d,t=l,n=f,yh(s).undoManager.undo(e,t,n);var e,t,n},redo:function(){return e=f,t=d.data,yh(s).undoManager.redo(e,t);var e,t},clear:function(){var e=d,t=f;yh(s).undoManager.clear(e,t)},reset:function(){var e=d;yh(s).undoManager.reset(e)},hasUndo:function(){return e=d,t=f,yh(s).undoManager.hasUndo(e,t);var e,t},hasRedo:function(){return e=d,t=f,yh(s).undoManager.hasRedo(e,t);var e,t},transact:function(e){return t=d,n=l,r=e,yh(s).undoManager.transact(t,n,r);var t,n,r},ignore:function(e){var t=l,n=e;yh(s).undoManager.ignore(t,n)},extra:function(e,t){var n=d,r=f,o=e,i=t;yh(s).undoManager.extra(n,r,o,i)}};return hh(s)||(r=d,o=l,i=au(!1),(n=s).on("init",function(){r.add()}),n.on("BeforeExecCommand",function(e){gb(e.command)||(gh(r,o),r.beforeChange())}),n.on("ExecCommand",function(e){gb(e.command)||a(e)}),n.on("ObjectResizeStart cut",function(){r.beforeChange()}),n.on("SaveContent ObjectResized blur",a),n.on("dragend",a),n.on("keyup",function(e){var t=e.keyCode;e.isDefaultPrevented()||((33<=t&&t<=36||37<=t&&t<=40||45===t||e.ctrlKey)&&(a(),n.nodeChanged()),46!==t&&8!==t||n.nodeChanged(),i.get()&&r.typing&&!1===fh(uh(n),r.data[0])&&(!1===n.isDirty()&&(n.setDirty(!0),n.fire("change",{level:r.data[0],lastLevel:null})),n.fire("TypingUndo"),i.set(!1),n.nodeChanged()))}),n.on("keydown",function(e){var t,n=e.keyCode;e.isDefaultPrevented()||(33<=n&&n<=36||37<=n&&n<=40||45===n?r.typing&&a(e):(t=e.ctrlKey&&!e.altKey||e.metaKey,!(n<16||20<n)||224===n||91===n||r.typing||t||(r.beforeChange(),mh(r,!0,o),r.add({},e),i.set(!0))))}),n.on("mousedown",function(e){r.typing&&a(e)}),n.on("input",function(e){e.inputType&&("insertReplacementText"===e.inputType||"insertText"===e.inputType&&null===e.data||"insertFromPaste"===e.inputType||"insertFromDrop"===e.inputType)&&a(e)}),n.on("AddUndo Undo Redo ClearUndos",function(e){e.isDefaultPrevented()||n.nodeChanged()})),(e=s).addShortcut("meta+z","","Undo"),e.addShortcut("meta+y,meta+shift+z","","Redo"),d;function a(e){mh(r,!1,o),r.add({},e)}}function hb(e){return"keydown"===e.type||"keyup"===e.type}function vb(e){var t=e.keyCode;return t===If.BACKSPACE||t===If.DELETE}function bb(e,t){return ze(Et.fromDom(t),e.getParam("inline_boundaries_selector","a[href],code,.mce-annotation","string"))}function yb(e,t,n){var r,o,i=(r=e,o=t,U(eu.DOM.getParents(n.container(),"*",o),r));return ve.from(i[i.length-1])}function Cb(e,t){if(!t)return t;var n=t.container(),r=t.offset();return e?Ir(n)?Vn(n.nextSibling)?cs(n.nextSibling,0):cs.after(n):Ur(t)?cs(n,r+1):t:Ir(n)?Vn(n.previousSibling)?cs(n.previousSibling,n.previousSibling.data.length):cs.before(n):zr(t)?cs(n,r-1):t}function xb(e){return po(e)||vo(e)}function wb(e,t){return Ve(e,t)?hr(t,xb,(n=e,function(e){return je(n,Et.fromDom(e.dom.parentNode))})):ve.none();var n}function Sb(e){var t,n,r;e.dom.isEmpty(e.getBody())&&(e.setContent(""),r=(n=(t=e).getBody()).firstChild&&t.dom.isBlock(n.firstChild)?n.firstChild:n,t.selection.setCursorLocation(r,0))}function Nb(e,t){return{from:e,to:t}}function Eb(e,t){return wb(Et.fromDom(e),Et.fromDom(t.container())).map(function(e){return{block:e,position:t}})}function kb(e){var t,n=z(t=Tn(e),go).fold(J(t),function(e){return t.slice(0,e)});return Y(n,In),n}function _b(e,t){return M(ym(t,e).reverse(),function(e){return Kr(e)}).each(In)}function Ab(e,t,n,r){if(Kr(n))return hm(n),rf(n.dom);0===U(Lt(r),function(e){return!Kr(e)}).length&&Kr(t)&&qt(r,Et.fromTag("br"));var o=nf(n.dom,cs.before(r.dom));return Y(kb(t),function(e){qt(r,e)}),_b(e,t),o}function Rb(e,t,n){if(Kr(n))return In(n),Kr(t)&&hm(t),rf(t.dom);var r=of(n.dom);return Y(kb(t),function(e){Ln(n,e)}),_b(e,t),r}function Db(e,t){jc(e,t.dom).map(function(e){return e.getNode()}).map(Et.fromDom).filter(Pr).each(In)}function Tb(e,t,n){return Db(!0,t),Db(!1,n),(Ve(o=n,r=t)?(i=ym(r,o),ve.from(i[i.length-1])):ve.none()).fold(R(Rb,e,t,n),R(Ab,e,t,n));var r,o,i}function Ob(e,t,n,r){return t?Tb(e,r,n):Tb(e,n,r)}function Bb(t,n){var e,r,o,i,a,u,s,c=Et.fromDom(t.getBody()),l=(e=c.dom,r=n,((o=t.selection.getRng()).collapsed?(a=r,u=Eb(i=e,cs.fromRangeStart(o)),s=u.bind(function(e){return Zl(a,i,e.position).bind(function(e){return Eb(i,e).map(function(e){return t=i,n=a,Kn((r=e).position.getNode())&&!1===Kr(r.block)?jc(!1,r.block.dom).bind(function(e){return e.isEqual(r.position)?Zl(n,t,e).bind(function(e){return Eb(t,e)}):ve.some(r)}).getOr(r):r;var t,n,r})})}),dn(u,s,Nb).filter(function(e){return!1===je(e.from.block,e.to.block)&&Ot((n=e).from.block).bind(function(t){return Ot(n.to.block).filter(function(e){return je(t,e)})}).isSome()&&!1===Gn((t=e).from.block.dom)&&!1===Gn(t.to.block.dom);var t,n})):ve.none()).bind(function(e){return Ob(c,n,e.from.block,e.to.block)}));return l.each(function(e){t.selection.setRng(e.toRange())}),l.isSome()}function Pb(e,t){var n=Et.fromDom(t),r=R(je,e);return pr(n,yo,r).isSome()}function Lb(e){var n,r,o,t,i,a,u,s,c,l,f=Et.fromDom(e.getBody()),d=e.selection.getRng();return a=d,c=nf((i=f).dom,cs.fromRangeStart(a)).isNone(),l=tf(i.dom,cs.fromRangeEnd(a)).isNone(),!Pb(u=i,(s=a).startContainer)&&!Pb(u,s.endContainer)&&c&&l?((t=e).setContent(""),t.selection.setCursorLocation(),!0):(n=f,r=e.selection,o=r.getRng(),dn(wb(n,Et.fromDom(o.startContainer)),wb(n,Et.fromDom(o.endContainer)),function(e,t){return!1===je(e,t)&&(o.deleteContents(),Ob(n,!0,e,t).each(function(e){r.setRng(e.toRange())}),!0)}).getOr(!1))}function Ib(e,t){return!e.selection.isCollapsed()&&Lb(e)}function Mb(e,t,n,r,o){return ve.from(t._selectionOverrides.showCaret(e,n,r,o))}function Fb(e,t){var n,r;return e.fire("BeforeObjectSelected",{target:t}).isDefaultPrevented()?ve.none():ve.some(((r=(n=t).ownerDocument.createRange()).selectNode(n),r))}function Ub(e,t,n){var r=nc(1,e.getBody(),t),o=cs.fromRangeStart(r),i=o.getNode();if(Ec(i))return Mb(1,e,i,!o.isAtEnd(),!1);var a=o.getNode(!0);if(Ec(a))return Mb(1,e,a,!1,!1);var u=e.dom.getParent(o.getNode(),function(e){return Ly(e)||Py(e)});return Ec(u)?Mb(1,e,u,!1,n):ve.none()}function zb(e,t,n){return t.collapsed?Ub(e,t,n).getOr(t):t}function Hb(e){return rp(e)||Zg(e)}function jb(e){return op(e)||ep(e)}function Vb(n,r,e,t,o,i){var a,u;return Mb(t,n,i.getNode(!o),o,!0).each(function(e){var t;r.collapsed?(t=r.cloneRange(),o?t.setEnd(e.startContainer,e.startOffset):t.setStart(e.endContainer,e.endOffset),t.deleteContents()):r.deleteContents(),n.selection.setRng(e)}),a=n.dom,Vn(u=e)&&0===u.data.length&&a.remove(u),!0}function qb(e,t){var n=e.selection.getRng();if(!Vn(n.commonAncestorContainer))return!1;var r=t?sc.Forwards:sc.Backwards,o=Mc(e.getBody()),i=R(ac,t?o.next:o.prev),a=t?Hb:jb,u=oc(r,e.getBody(),n),s=Cb(t,i(u));if(!s||!uc(u,s))return!1;if(a(s))return Vb(e,n,u.getNode(),r,t,s);var c=i(s);return!!(c&&a(c)&&uc(s,c))&&Vb(e,n,u.getNode(),r,t,c)}function $b(l,f,d){return Zl(f,l,d).bind(function(e){return s=e.getNode(),yo(Et.fromDom(s))||vo(Et.fromDom(s))||(o=l,u=e,rc(!(i=f),a=d).fold(function(){return rc(i,u).fold(D,c)},c))?ve.none():f&&Gn(e.getNode())||!1===f&&Gn(e.getNode(!0))?(t=l,n=d,r=e.getNode(!1===f),wb(Et.fromDom(t),Et.fromDom(n.getNode())).map(function(e){return Kr(e)?Iy.remove(e.dom):Iy.moveToElement(r)}).orThunk(function(){return ve.some(Iy.moveToElement(r))})):f&&op(d)||!1===f&&rp(d)?ve.some(Iy.moveToPosition(e)):ve.none();var t,n,r,o,i,a,u,s;function c(e){return Br(Et.fromDom(e))&&!Qs(a,u,o)}})}function Wb(e,t){return ve.from(bf(e.getBody(),t))}function Kb(m,g){var e=m.selection.getNode();return Wb(m,e).filter(Gn).fold(function(){return s=m.getBody(),l=nc((c=g)?1:-1,s,m.selection.getRng()),f=cs.fromRangeStart(l),d=Et.fromDom(s),(!1===c&&op(f)?ve.some(Iy.remove(f.getNode(!0))):c&&rp(f)?ve.some(Iy.remove(f.getNode())):!1===c&&rp(f)&&_m(d,f)?cp(d,f).map(function(e){return Iy.remove(e.getNode())}):c&&op(f)&&km(d,f)?lp(d,f).map(function(e){return Iy.remove(e.getNode())}):(r=s,e=c,a=(o=f).getNode(!1===(i=e)),u=i?"after":"before",Hn(a)&&a.getAttribute("data-mce-caret")===u?(n=o.getNode(!1===(t=e)),(t&&Gn(n.nextSibling)?ve.some(Iy.moveToElement(n.nextSibling)):!1===t&&Gn(n.previousSibling)?ve.some(Iy.moveToElement(n.previousSibling)):ve.none()).fold(function(){return $b(r,e,o)},ve.some)):$b(r,e,o).bind(function(e){return t=r,n=o,e.fold(function(e){return ve.some(Iy.remove(e))},function(e){return ve.some(Iy.moveToElement(e))},function(e){return Qs(n,e,t)?ve.none():ve.some(Iy.moveToPosition(e))});var t,n}))).exists(function(e){return e.fold(function(e){return o._selectionOverrides.hideFakeCaret(),Qm(o,i,Et.fromDom(e)),!0},(r=i=g,function(e){var t=r?cs.before(e):cs.after(e);return n.selection.setRng(t.toRange()),!0}),(t=n=o=m,function(e){return t.selection.setRng(e.toRange()),!0}));var t,n,r,o,i});var r,e,o,t,n,i,a,u,s,c,l,f,d},w)}function Xb(e,t){var n=e.selection.getNode();return!(!Gn(n)||Jn(n))&&Wb(e,n.parentNode).filter(Gn).fold(function(){return Y(yu(Et.fromDom(e.getBody()),".mce-offscreen-selection"),In),Qm(e,t,Et.fromDom(e.selection.getNode())),Sb(e),!0},w)}function Yb(e){var t,n=e.dom,r=e.selection,o=bf(e.getBody(),r.getNode());return Yn(o)&&n.isBlock(o)&&n.isEmpty(o)&&(t=n.create("br",{"data-mce-bogus":"1"}),n.setHTML(o,""),o.appendChild(t),r.setRng(cs.before(t).toRange())),!0}function Gb(e,t){return(e.selection.isCollapsed()?Kb:Xb)(e,t)}function Jb(e,t){return!!e.selection.isCollapsed()&&(n=e,r=t,o=cs.fromRangeStart(n.selection.getRng()),Zl(r,n.getBody(),o).filter(function(e){return(r?Jg:Qg)(e)}).bind(function(e){return ve.from(Zs(r?0:-1,e))}).exists(function(e){return n.selection.select(e),!0}));var n,r,o}function Qb(e){return My(e)&&e.data[0]===So}function Zb(e){return My(e)&&e.data[e.data.length-1]===So}function ey(e){return e.ownerDocument.createTextNode(So)}function ty(e,t){return(e?function(e){if(My(e.previousSibling))return Zb(e.previousSibling)||e.previousSibling.appendData(So),e.previousSibling;if(My(e))return Qb(e)||e.insertData(0,So),e;var t=ey(e);return e.parentNode.insertBefore(t,e),t}:function(e){if(My(e.nextSibling))return Qb(e.nextSibling)||e.nextSibling.insertData(0,So),e.nextSibling;if(My(e))return Zb(e)||e.appendData(So),e;var t=ey(e);return e.nextSibling?e.parentNode.insertBefore(t,e.nextSibling):e.parentNode.appendChild(t),t})(t)}function ny(e,t){return Vn(e.container())?ty(t,e.container()):ty(t,e.getNode())}function ry(e,t){var n=t.get();return n&&e.container()===n&&Ir(n)}function oy(n,e){return e.fold(function(e){Cc(n.get());var t=Fy(e);return n.set(t),ve.some(cs(t,t.length-1))},function(e){return rf(e).map(function(e){if(ry(e,n))return cs(n.get(),1);Cc(n.get());var t=ny(e,!0);return n.set(t),cs(t,1)})},function(e){return of(e).map(function(e){if(ry(e,n))return cs(n.get(),n.get().length-1);Cc(n.get());var t=ny(e,!1);return n.set(t),cs(t,t.length-1)})},function(e){Cc(n.get());var t=Uy(e);return n.set(t),ve.some(cs(t,1))})}function iy(e,t){for(var n=0;n<e.length;n++){var r=e[n].apply(null,t);if(r.isSome())return r}return ve.none()}function ay(e,t){return Js(t,e)||e}function uy(e,t,n){var r=Oy(n),o=ay(t,r.container());return yb(e,o,r).fold(function(){return tf(o,r).bind(R(yb,e,o)).map(function(e){return zy.before(e)})},ve.none)}function sy(e,t){return null===qc(e,t)}function cy(e,t,n){return yb(e,t,n).filter(R(sy,t))}function ly(e,t,n){var r=By(n);return cy(e,t,r).bind(function(e){return nf(e,r).isNone()?ve.some(zy.start(e)):ve.none()})}function fy(e,t,n){var r=Oy(n);return cy(e,t,r).bind(function(e){return tf(e,r).isNone()?ve.some(zy.end(e)):ve.none()})}function dy(e,t,n){var r=By(n),o=ay(t,r.container());return yb(e,o,r).fold(function(){return nf(o,r).bind(R(yb,e,o)).map(function(e){return zy.after(e)})},ve.none)}function my(e){return!1===(t=Hy(e),"rtl"===eu.DOM.getStyle(t,"direction",!0)||(n=t.textContent,Ty.test(n)));var t,n}function gy(e,t,n){return iy([uy,ly,fy,dy],[e,t,n]).filter(my)}function py(e){return e.fold(J("before"),J("start"),J("end"),J("after"))}function hy(e){return e.fold(zy.before,zy.before,zy.after,zy.after)}function vy(e){return e.fold(zy.start,zy.start,zy.end,zy.end)}function by(a,e,u,t,n,s){return dn(yb(e,u,t),yb(e,u,n),function(e,t){return e!==t&&(r=t,o=Js(e,n=u),i=Js(r,n),o&&o===i)?zy.after(a?e:t):s;var n,r,o,i}).getOr(s)}function yy(e,r){return e.fold(w,function(e){return n=r,!(py(t=e)===py(n)&&Hy(t)===Hy(n));var t,n})}function Cy(e,t){return e?t.fold(i(ve.some,zy.start),ve.none,i(ve.some,zy.after),ve.none):t.fold(ve.none,i(ve.some,zy.before),ve.none,i(ve.some,zy.end))}function xy(e,a,u,s){var t=Cb(e,s),c=gy(a,u,t);return gy(a,u,t).bind(R(Cy,e)).orThunk(function(){return n=a,r=u,o=c,i=Cb(t=e,s),Zl(t,r,i).map(R(Cb,t)).fold(function(){return o.map(hy)},function(e){return gy(n,r,e).map(R(by,t,n,r,i,e)).filter(R(yy,o))}).filter(my);var t,n,r,o,i})}function wy(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r=window.console;r&&(r.error||r.log).apply(r,Ae([e],t,!1))}var Sy,Ny,Ey=function(t,e){var n=t.editorManager.baseURL+"/skins/content",r="content"+t.editorManager.suffix+".css",o=!0===t.inline;return A(e,function(e){return/^[a-z0-9\-]+$/i.test(e)&&!o?n+"/"+e+"/"+r:t.documentBaseURI.toAbsolute(e)})},ky=0,_y=Nt.each,Ay=eu.DOM,Ry=[9,27,If.HOME,If.END,19,20,44,144,145,33,34,45,16,17,18,91,92,93,If.DOWN,If.UP,If.LEFT,If.RIGHT].concat(xt.browser.isFirefox()?[224]:[]),Dy="data-mce-placeholder",Ty=/[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/,Oy=R(Cb,!0),By=R(Cb,!1),Py=Yn,Ly=Gn,Iy=ir([{remove:["element"]},{moveToElement:["element"]},{moveToPosition:["position"]}]),My=Vn,Fy=R(ty,!0),Uy=R(ty,!1),zy=ir([{before:["element"]},{start:["element"]},{end:["element"]},{after:["element"]}]),Hy=function(e){return e.fold(u,u,u,u)};function jy(e,t,n){var r=e?1:-1;return t.setRng(cs(n.container(),n.offset()+r).toRange()),t.getSel().modify("move",e?"forward":"backward","word"),!0}function Vy(e,t){return e===sc.Backwards?q(t):t}function qy(e,t,n,r){for(var o,i,a,u,s=Mc(n),c=r,l=[];c;){var f=(a=s,u=c,t===sc.Forwards?a.next(u):a.prev(u));if(!f)break;if(Kn(f.getNode(!1)))return t===sc.Forwards?{positions:Vy(t,l).concat([f]),breakType:Sy.Br,breakAt:ve.some(f)}:{positions:Vy(t,l),breakType:Sy.Br,breakAt:ve.some(f)};if(f.isVisible()){if(e(c,f)){var d=(o=c,Kn((i=f).getNode(t===sc.Forwards))?Sy.Br:!1===Qs(o,i)?Sy.Block:Sy.Wrap);return{positions:Vy(t,l),breakType:d,breakAt:ve.some(f)}}l.push(f),c=f}else c=f}return{positions:Vy(t,l),breakType:Sy.Eol,breakAt:ve.none()}}function $y(n,r,o,e){return r(o,e).breakAt.map(function(e){var t=r(o,e).positions;return n===sc.Backwards?t.concat(e):[e].concat(t)}).getOr([])}function Wy(e,i){return L(e,function(e,o){return e.fold(function(){return ve.some(o)},function(r){return dn(Q(r.getClientRects()),Q(o.getClientRects()),function(e,t){var n=Math.abs(i-e.left);return Math.abs(i-t.left)<=n?o:r}).or(e)})},ve.none())}function Ky(t,e){return Q(e.getClientRects()).bind(function(e){return Wy(t,e.left)})}function Xy(n){function e(e){return A(e,function(e){var t=Ru(e);return t.node=n,t})}if(Hn(n))return e(n.getClientRects());if(Vn(n)){var t=n.ownerDocument.createRange();return t.setStart(n,0),t.setEnd(n,n.data.length),e(t.getClientRects())}}function Yy(e){return H(e,Xy)}R(xy,!1),R(xy,!0),(Ny=Sy={})[Ny.Br=0]="Br",Ny[Ny.Block=1]="Block",Ny[Ny.Wrap=2]="Wrap",Ny[Ny.Eol=3]="Eol";var Gy,Jy,Qy=R(qy,cs.isAbove,-1),Zy=R(qy,cs.isBelow,1),e0=R($y,-1,Qy),t0=R($y,1,Zy);function n0(o,i,a,e,u,t){function n(e){var t=Yy([e]);-1===o&&(t=t.reverse());for(var n=0;n<t.length;n++){var r=t[n];if(!a(r,l)){if(0<c.length&&i(r,pe(c))&&s++,r.line=s,u(r))return!0;c.push(r)}}}var s=0,c=[],l=pe(t.getClientRects());if(!l)return c;var r=t.getNode();return n(r),function(e,t,n,r){for(;r=Gs(r,e,qr,t);)if(n(r))return}(o,e,n,r),c}function r0(t){return function(e){return e.line>t}}function o0(t){return function(e){return e.line===t}}function i0(e,t){return Math.abs(e.left-t)}function a0(e,t){return Math.abs(e.right-t)}function u0(e,t){return e>=t.left&&e<=t.right}function s0(e,t){return e>=t.top&&e<=t.bottom}function c0(e,o,i){return void 0===i&&(i=w),me(e,function(e,t){if(u0(o,t))return i(t)?t:e;if(u0(o,e))return i(e)?e:t;var n=Math.min(i0(e,o),a0(e,o)),r=Math.min(i0(t,o),a0(t,o));return r===n&&se(t,"node")&&ZC(t.node)||r<n?t:e})}function l0(e,t,n,r,o){var i=e1(r,e,qr,t,!o);do{if(!i||n(i))return}while(i=e1(i,e,qr,t))}function f0(e,t,n){function r(e){return!cn(e.node)&&!Qn(e.node)}var o,i,a,u=Yy(U(xe(e.getElementsByTagName("*")),Xs)),s=U(u,R(s0,n));if((a=c0(s,t,r))&&((a=c0(function(e,r,t){function n(t,e){var n=U(Yy([e]),function(e){return!t(e,r)});return o=o.concat(n),0===n.length}void 0===t&&(t=!0);var o=[];return o.push(r),l0(Gy.Up,e,R(n,Ou),r.node,t),l0(Gy.Down,e,R(n,Bu),r.node,t),o}(e,a,r(a)),t,r))&&Xs(a.node)))return{node:(o=a).node,before:i0(o,i=t)<a0(o,i)};return null}function d0(e,t){e.selection.setRng(t),nd(e,e.selection.getRng())}function m0(e,t,n){return ve.some(zb(e,t,n))}function g0(e,t,n,r,o,i){var a=t===sc.Forwards,u=Mc(e.getBody()),s=R(ac,a?u.next:u.prev),c=a?r:o;if(!n.collapsed){var l=Lu(n);if(i(l))return Mb(t,e,l,t===sc.Backwards,!1)}var f=oc(t,e.getBody(),n);if(c(f))return Fb(e,f.getNode(!a));var d=Cb(a,s(f)),m=jr(n);if(!d)return m?ve.some(n):ve.none();if(c(d))return Mb(t,e,d.getNode(!a),a,!1);var g=s(d);return g&&c(g)&&uc(d,g)?Mb(t,e,g.getNode(!a),a,!1):m?m0(e,d.toRange(),!1):ve.none()}function p0(t,e,n,r,o,i){var a=oc(e,t.getBody(),n),u=pe(a.getClientRects()),s=e===Gy.Down;if(!u)return ve.none();var c,l=U((s?QC:JC)(t.getBody(),r0(1),a),o0(1)),f=u.left,d=c0(l,f);if(d&&i(d.node)){var m=Math.abs(f-d.left),g=Math.abs(f-d.right);return Mb(e,t,d.node,m<g,!1)}if(c=r(a)?a.getNode():o(a)?a.getNode(!0):Lu(n)){var p=function(e,t,n,r){function o(e){return pe(e.getClientRects())}var i,a,u,s=Mc(t),c=[],l=0,f=1===e?(i=s.next,a=Bu,u=Ou,cs.after(r)):(i=s.prev,a=Ou,u=Bu,cs.before(r)),d=o(f);do{if(f.isVisible()){var m=o(f);if(!u(m,d)){0<c.length&&a(m,pe(c))&&l++;var g=Ru(m);if(g.position=f,g.line=l,n(g))return c;c.push(g)}}}while(f=i(f));return c}(e,t.getBody(),r0(1),c),h=c0(U(p,o0(1)),f);if(h)return m0(t,h.position.toRange(),!1);if(h=pe(U(p,o0(0))))return m0(t,h.position.toRange(),!1)}return 0===l.length?t1(t,s).filter(s?o:r).map(function(e){return zb(t,e.toRange(),!1)}):ve.none()}function h0(t,e,n){return t1(t,e).filter(n).exists(function(e){return t.selection.setRng(e.toRange()),!0})}function v0(e,t){var n=e.dom.createRng();n.setStart(t.container(),t.offset()),n.setEnd(t.container(),t.offset()),e.selection.setRng(n)}function b0(e,t){e?t.setAttribute("data-mce-selected","inline-boundary"):t.removeAttribute("data-mce-selected")}function y0(t,e,n){return oy(e,n).map(function(e){return v0(t,e),n})}function C0(e,t,n){return!!Ms(e)&&(o=t,i=n,a=(r=e).getBody(),u=cs.fromRangeStart(r.selection.getRng()),xy(i,R(bb,r),a,u).bind(function(e){return y0(r,o,e)}).isSome());var r,o,i,a,u}function x0(e,t,n){return!!Ms(t)&&(r=e,i=(o=t).selection.getRng(),a=r?cs.fromRangeEnd(i):cs.fromRangeStart(i),!!y(o.selection.getSel().modify)&&(r&&Ur(a)?jy(!0,o.selection,a):!(r||!zr(a))&&jy(!1,o.selection,a)));var r,o,i,a}function w0(g){var p=au(null),h=R(bb,g);return g.on("NodeChange",function(e){var n,r,o,t,i,a,u,s,c,l,f,d,m;!Ms(g)||xt.browser.isIE()&&e.initial||(i=h,a=g.dom,u=e.parents,Y($(s=U(A(yu(Et.fromDom(a.getRoot()),'*[data-mce-selected="inline-boundary"]'),function(e){return e.dom}),i),c=U(u,i)),R(b0,!1)),Y($(c,s),R(b0,!0)),f=p,(l=g).selection.isCollapsed()&&!0!==l.composing&&f.get()&&(d=cs.fromRangeStart(l.selection.getRng()),cs.isTextPosition(d)&&!1===(Ur(m=d)||zr(m))&&(v0(l,qs(f.get(),d)),f.set(null))),n=h,r=g,o=p,t=e.parents,r.selection.isCollapsed()&&Y(U(t,n),function(e){var t=cs.fromRangeStart(r.selection.getRng());gy(n,r.getBody(),t).bind(function(e){return y0(r,o,e)})}))}),p}function S0(n,t,r){if(Ms(n)){var e=t1(n,t).getOrThunk(function(){var e=n.selection.getRng();return t?cs.fromRangeEnd(e):cs.fromRangeStart(e)});return gy(R(bb,n),n.getBody(),e).exists(function(e){var t=hy(e);return oy(r,t).exists(function(e){return v0(n,e),!0})})}return!1}function N0(t,n){return function(e){return oy(n,e).exists(function(e){return v0(t,e),!0})}}function E0(r,o,i,a){var u=r.getBody(),s=R(bb,r);r.undoManager.ignore(function(){var e,t,n;r.selection.setRng((e=i,t=a,(n=document.createRange()).setStart(e.container(),e.offset()),n.setEnd(t.container(),t.offset()),n)),r.execCommand("Delete"),gy(s,u,cs.fromRangeStart(r.selection.getRng())).map(vy).map(N0(r,o))}),r.nodeChanged()}function k0(e,t,n){if(e.selection.isCollapsed()&&Ms(e)){var r=cs.fromRangeStart(e.selection.getRng());return o=t,a=n,u=r,s=(i=e).getBody(),c=Js(u.container(),s)||s,l=R(bb,i),(f=gy(l,c,u)).bind(function(e){return a?e.fold(J(ve.some(vy(e))),ve.none,J(ve.some(hy(e))),ve.none):e.fold(ve.none,J(ve.some(hy(e))),ve.none,J(ve.some(vy(e))))}).map(N0(i,o)).getOrThunk(function(){var t=Hc(a,c,u),e=t.bind(function(e){return gy(l,c,e)});return dn(f,e,function(){return yb(l,c,u).exists(function(e){return!!dn(rf(o=e),of(o),function(e,t){var n=Cb(!0,e),r=Cb(!1,t);return tf(o,n).forall(function(e){return e.isEqual(r)})}).getOr(!0)&&(Qm(i,a,Et.fromDom(e)),!0);var o})}).orThunk(function(){return e.bind(function(e){return t.map(function(e){return a?E0(i,o,u,e):E0(i,o,e,u),!0})})}).getOr(!1)})}var i,o,a,u,s,c,l,f;return!1}function _0(e){return 1===zt(e)}function A0(g,p){var t,e=Et.fromDom(g.getBody()),n=Et.fromDom(g.selection.getStart()),h=U(z(t=ym(n,e),go).fold(J(t),function(e){return t.slice(0,e)}),_0);return Z(h).exists(function(e){var t,n,r,o,i,a,u,s,c,l=cs.fromRangeStart(g.selection.getRng()),f=p,d=l,m=e.dom;return!(!dn(rf(m),of(m),function(e,t){var n=Cb(!0,e),r=Cb(!1,t),o=Cb(!1,d);return f?tf(m,o).exists(function(e){return e.isEqual(r)&&d.isEqual(n)}):nf(m,o).exists(function(e){return e.isEqual(n)&&d.isEqual(r)})}).getOr(!0)||Vc((t=e).dom)&&Mg(t.dom)||(n=p,o=e,0===(c=A(U(h,R(Wg,r=g)),function(e){return e.dom})).length?Qm(r,n,o):(a=o.dom,s=Vg(c,(u=Ug(!1)).dom),qt(Et.fromDom(a),u),In(Et.fromDom(a)),i=cs(s,0),r.selection.setRng(i.toRange())),0))})}function R0(e,t){return!!e.selection.isCollapsed()&&A0(e,t)}function D0(e,t,n){return e._selectionOverrides.hideFakeCaret(),Qm(e,t,Et.fromDom(n)),!0}function T0(e,t){return e.selection.isCollapsed()?(i=e,u=(a=t)?Zg:ep,s=a?sc.Forwards:sc.Backwards,c=oc(s,i.getBody(),i.selection.getRng()),u(c)?D0(i,a,c.getNode(!a)):ve.from(Cb(a,c)).filter(function(e){return u(e)&&uc(c,e)}).exists(function(e){return D0(i,a,e.getNode(!a))})):(r=t,o=(n=e).selection.getNode(),!!Qn(o)&&D0(n,r,o));var n,r,o,i,a,u,s,c}function O0(e){var t=parseInt(e,10);return isNaN(t)?0:t}function B0(e,t){return(e||"table"===kt(t)?"margin":"padding")+("rtl"===wn(t,"direction")?"-right":"-left")}function P0(e){var n,t=o1(e);return!e.mode.isReadOnly()&&(1<t.length||(n=e,j(t,function(e){var t=Sn(e,B0(Os(n),e)).map(O0).getOr(0);return"false"!==n.dom.getContentEditable(e.dom)&&0<t})))}function L0(e){return ho(e)||vo(e)}function I0(e,s){var c=e.dom,t=e.selection,n=e.formatter,r=e.getParam("indentation","40px","string"),l=/[a-z%]+$/i.exec(r)[0],f=parseInt(r,10),d=Os(e),o=ks(e);e.queryCommandState("InsertUnorderedList")||e.queryCommandState("InsertOrderedList")||""!==o||c.getParent(t.getNode(),c.isBlock)||n.apply("div"),Y(o1(e),function(e){var t,n=c,r=s,o=f,i=l,a=e.dom,u=B0(d,Et.fromDom(a));"outdent"===r?(t=Math.max(0,O0(a.style[u])-o),n.setStyle(a,u,t?t+i:"")):(t=O0(a.style[u])+o+i,n.setStyle(a,u,t))})}function M0(e,t){if(e.selection.isCollapsed()&&P0(e)){var n=e.dom,r=e.selection.getRng(),o=cs.fromRangeStart(r),i=n.getParent(r.startContainer,n.isBlock);if(null!==i&&ip(Et.fromDom(i),o))return I0(e,"outdent"),!0}return!1}function F0(e,t){e.getDoc().execCommand(t,!1,null)}function U0(e){return void 0===e.touches||1!==e.touches.length?ve.none():ve.some(e.touches[0])}function z0(e,t){return Ee(e,t.nodeName)}function H0(e){var t,n,r,o=e.dom,i=e.selection,a=e.schema,u=a.getBlockElements(),s=i.getStart(),c=e.getBody(),l=ks(e);if(s&&Hn(s)&&l){var f=c.nodeName.toLowerCase();if(a.isValidChild(f,l.toLowerCase())&&(d=u,m=c,g=s,!F(bm(Et.fromDom(g),Et.fromDom(m)),function(e){return z0(d,e.dom)}))){for(var d,m,g,p,h,v=i.getRng(),b=v.startContainer,y=v.startOffset,C=v.endContainer,x=v.endOffset,w=Cd(e),s=c.firstChild;s;)p=u,Vn(h=s)||Hn(h)&&!z0(p,h)&&!Qc(h)?function(e,t){if(Vn(t)){if(0===t.nodeValue.length)return 1;if(/^\s+$/.test(t.nodeValue)&&(!t.nextSibling||z0(e,t.nextSibling)))return 1}}(u,s)?(s=(n=s).nextSibling,o.remove(n)):(t||(t=o.create(l,_s(e)),s.parentNode.insertBefore(t,s),r=!0),s=(n=s).nextSibling,t.appendChild(n)):(t=null,s=s.nextSibling);r&&w&&(v.setStart(b,y),v.setEnd(C,x),i.setRng(v),e.nodeChanged())}}}function j0(e,t){t.hasAttribute("data-mce-caret")&&(Hr(t),e.selection.setRng(e.selection.getRng()),e.selection.scrollIntoView(t))}function V0(e,t){var n=br(Et.fromDom(e.getBody()),"*[data-mce-caret]").map(function(e){return e.dom}).getOrNull();if(n)return"compositionstart"===t.type?(t.preventDefault(),t.stopPropagation(),void j0(e,n)):void(Fr(n)&&(j0(e,n),e.undoManager.add()))}function q0(e,t,n){var r,o,i,a=Mc(e.getBody()),u=R(ac,1===t?a.next:a.prev);!n.collapsed||""===ks(e)||(r=e.dom.getParent(n.startContainer,"PRE"))&&(u(cs.fromRangeStart(n))||(i=e.dom.create(ks(e)),(!xt.ie||11<=xt.ie)&&(i.innerHTML='<br data-mce-bogus="1">'),o=i,1===t?e.$(r).after(o):e.$(r).before(o),e.selection.select(o,!0),e.selection.collapse()))}function $0(t,e){return n=t,r=e?sc.Forwards:sc.Backwards,o=n.selection.getRng(),g0(n,r,o,rp,op,i1).orThunk(function(){return q0(n,r,o),ve.none()}).exists(function(e){return d0(t,e),!0});var n,r,o}function W0(t,e){return r=e?1:-1,o=(n=t).selection.getRng(),p0(n,r,o,function(e){return rp(e)||tp(e)},function(e){return op(e)||np(e)},i1).orThunk(function(){return q0(n,r,o),ve.none()}).exists(function(e){return d0(t,e),!0});var n,r,o}function K0(e,t){return h0(e,t,t?op:rp)}function X0(e){return T(["figcaption"],kt(e))}function Y0(e){var t=document.createRange();return t.setStartBefore(e.dom),t.setEndBefore(e.dom),t}function G0(e,t,n){(n?Ln:Wt)(e,t)}function J0(h,v){var b=Et.fromDom(h.getBody()),y=cs.fromRangeStart(h.selection.getRng()),C=ks(h),x=_s(h),e=y,t=R(je,b);return hr(Et.fromDom(e.container()),go,t).filter(X0).exists(function(){if(d=b,m=y,v?(p=d.dom,Zy(p,m).breakAt.isNone()):(g=d.dom,Qy(g,m).breakAt.isNone())){var e=(t=b,r=x,o=v,""===(n=C)?(l=o,G0(t,f=Et.fromTag("br"),l),Y0(f)):(i=t,a=o,u=r,s=Et.fromTag(n),c=Et.fromTag("br"),hn(s,u),Ln(s,c),G0(i,s,a),Y0(c)));return h.selection.setRng(e),!0}var t,n,r,o,i,a,u,s,c,l,f,d,m,g,p;return!1})}function Q0(e,t){return!!e.selection.isCollapsed()&&J0(e,t)}function Z0(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return function(){return e.apply(null,t)}}function eC(e,t){return M((n=t,H(A(e,function(e){return _e({shiftKey:!1,altKey:!1,ctrlKey:!1,metaKey:!1,keyCode:0,action:te},e)}),function(e){return n.keyCode===e.keyCode&&n.shiftKey===e.shiftKey&&n.altKey===e.altKey&&n.ctrlKey===e.ctrlKey&&n.metaKey===e.metaKey?[e]:[]})),function(e){return e.action()});var n}function tC(t,e){var n=e?sc.Forwards:sc.Backwards,r=t.selection.getRng();return g0(t,n,r,Zg,ep,Qn).exists(function(e){return d0(t,e),!0})}function nC(t,e){var n=e?1:-1,r=t.selection.getRng();return p0(t,n,r,Zg,ep,Qn).exists(function(e){return d0(t,e),!0})}function rC(e,t){return h0(e,t,t?ep:Zg)}function oC(e,t,n,r,o){var i,a=yu(Et.fromDom(n),"td,th,caption").map(function(e){return e.dom}),u=U((i=e,H(a,function(e){var t,n={left:(t=Ru(e.getBoundingClientRect())).left- -1,top:t.top- -1,right:t.right+-2,bottom:t.bottom+-2,width:t.width+-1,height:t.height+-1};return[{x:n.left,y:i(n),cell:e},{x:n.right,y:i(n),cell:e}]})),function(e){return t(e,o)}),s=r,c=o;return L(u,function(e,r){return e.fold(function(){return ve.some(r)},function(e){var t=Math.sqrt(Math.abs(e.x-s)+Math.abs(e.y-c)),n=Math.sqrt(Math.abs(r.x-s)+Math.abs(r.y-c));return ve.some(n<t?r:e)})},ve.none()).map(function(e){return e.cell})}function iC(e,t,n){var r,o,i=e(t,n);return i.breakType===Sy.Wrap&&0===i.positions.length||!Kn(n.getNode())&&i.breakType===Sy.Br&&1===i.positions.length?(r=e,o=t,!i.breakAt.exists(function(e){return r(o,e).breakAt.isSome()})):i.breakAt.isNone()}function aC(t,e,n,r){var o,i,a,u=t.selection.getRng(),s=e?1:-1;return!(!Ks()||(o=e,i=n,a=cs.fromRangeStart(u),!jc(!o,i).exists(function(e){return e.isEqual(a)}))||(Mb(s,t,n,!e,!1).each(function(e){d0(t,e)}),0))}function uC(u,s,c){var e,t,n=(e=!!s,t=c.getNode(e),Hn(t)&&"TABLE"===t.nodeName?ve.some(t):ve.none()),r=!1===s;n.fold(function(){return d0(u,c.toRange())},function(a){return jc(r,u.getBody()).filter(function(e){return e.isEqual(c)}).fold(function(){return d0(u,c.toRange())},function(e){var n,r,o=s,i=a,t=c;(r=ks(n=u))?n.undoManager.transact(function(){var e=Et.fromTag(r);hn(e,_s(n)),Ln(e,Et.fromTag("br")),(o?$t:qt)(Et.fromDom(i),e);var t=n.dom.createRng();t.setStart(e.dom,0),t.setEnd(e.dom,0),d0(n,t)}):d0(n,t.toRange())})})}function sC(e,t,n,r){var o,i,a,u,s,c,l,f,d,m,g=e.selection.getRng(),p=cs.fromRangeStart(g),h=e.getBody();if(t||!s1(r,p))return!(!t||!c1(r,p))&&(o=h,d=i=n,uC(e,t,v=Z((m=a=p).getClientRects()).bind(function(e){return u1(d,e.left,e.top)}).bind(function(e){return Ky(rf(t=e).map(function(e){return[e].concat(Zy(t,e).positions)}).getOr([]),m);var t}).orThunk(function(){return Q(a.getClientRects()).bind(function(e){return Wy(t0(o,cs.after(i)),e.left)})}).getOr(cs.after(i))),!0);var v=(u=h,l=s=n,Q((f=c=p).getClientRects()).bind(function(e){return a1(l,e.left,e.top)}).bind(function(e){return Ky(of(t=e).map(function(e){return Qy(t,e).positions.concat(e)}).getOr([]),f);var t}).orThunk(function(){return Q(c.getClientRects()).bind(function(e){return Wy(e0(u,cs.before(s)),e.left)})}).getOr(cs.before(s)));return uC(e,t,v),!0}function cC(n,r,o){return ve.from(n.dom.getParent(n.selection.getNode(),"td,th")).bind(function(t){return ve.from(n.dom.getParent(t,"table")).map(function(e){return o(n,r,e,t)})}).getOr(!1)}function lC(e,t){return cC(e,t,aC)}function fC(e,t){return cC(e,t,sC)}function dC(e,t){var n,r,o=t,i=e.dom,a=e.schema.getMoveCaretBeforeOnEnterElements();if(t){!/^(LI|DT|DD)$/.test(t.nodeName)||(r=function(e){for(;e;){if(1===e.nodeType||3===e.nodeType&&e.data&&/[\r\n\s]/.test(e.data))return e;e=e.nextSibling}}(t.firstChild))&&/^(UL|OL|DL)$/.test(r.nodeName)&&t.insertBefore(i.doc.createTextNode(wo),t.firstChild);var u=i.createRng();if(t.normalize(),t.hasChildNodes()){for(var s=new Dr(t,t);n=s.current();){if(Vn(n)){u.setStart(n,0),u.setEnd(n,0);break}if(a[n.nodeName.toLowerCase()]){u.setStartBefore(n),u.setEndBefore(n);break}o=n,n=s.next()}n||(u.setStart(o,0),u.setEnd(o,0))}else Kn(t)?t.nextSibling&&i.isBlock(t.nextSibling)?(u.setStartBefore(t),u.setEndBefore(t)):(u.setStartAfter(t),u.setEndAfter(t)):(u.setStart(t,0),u.setEnd(t,0));e.selection.setRng(u),nd(e,u)}}function mC(e){return ve.from(e.dom.getParent(e.selection.getStart(!0),e.dom.isBlock))}function gC(e,t){return e&&e.parentNode&&e.parentNode.nodeName===t}function pC(e){return e&&/^(OL|UL|LI)$/.test(e.nodeName)}function hC(e){var t=e.parentNode;return/^(LI|DT|DD)$/.test(t.nodeName)?t:e}function vC(e,t,n){for(var r=e[n?"firstChild":"lastChild"];r&&!Hn(r);)r=r[n?"nextSibling":"previousSibling"];return r===t}function bC(e){e.innerHTML='<br data-mce-bogus="1">'}function yC(e,t){return e.nodeName===t||e.previousSibling&&e.previousSibling.nodeName===t}function CC(e,t){return t&&e.isBlock(t)&&!/^(TD|TH|CAPTION|FORM)$/.test(t.nodeName)&&!/^(fixed|absolute)/i.test(t.style.position)&&"true"!==e.getContentEditable(t)}function xC(e,t,n){return!1===Vn(t)?n:e?1===n&&t.data.charAt(n-1)===So?0:n:n===t.data.length-1&&t.data.charAt(n)===So?t.data.length:n}function wC(e,t){for(var n,r=e.getRoot(),o=t;o!==r&&"false"!==e.getContentEditable(o);)"true"===e.getContentEditable(o)&&(n=o),o=o.parentNode;return o!==r?n:r}function SC(e,t){var n=ks(e);n&&n.toLowerCase()===t.tagName.toLowerCase()&&function(e,o,t){var i=e.dom;ve.from(t.style).map(i.parseStyle).each(function(e){var t=Nn(Et.fromDom(o)),n=_e(_e({},t),e);i.setStyles(o,n)}),dn(ve.from(t.class).map(function(e){return e.split(/\s+/)}),ve.from(o.className).map(function(e){return U(e.split(/\s+/),function(e){return""!==e})}),function(t,e){var n=U(e,function(e){return!T(t,e)}),r=Ae(Ae([],t,!0),n,!0);i.setAttrib(o,"class",r.join(" "))});var n=["style","class"],r=ae(t,function(e,t){return!T(n,t)});i.setAttribs(o,r)}(e,t,_s(e))}function NC(a,e){function t(e){var t,n=m,r=l.getTextInlineElements(),o=e||"TABLE"===C||"HR"===C?c.create(e||p):b.cloneNode(!1),i=o;if(!1===a.getParam("keep_styles",!0))c.setAttrib(o,"style",null),c.setAttrib(o,"class",null);else for(;r[n.nodeName]&&(Vc(n)||Qc(n)||(t=n.cloneNode(!1),c.setAttrib(t,"id",""),o.hasChildNodes()?t.appendChild(o.firstChild):i=t,o.appendChild(t))),(n=n.parentNode)&&n!==F;);return SC(a,o),bC(i),o}function n(e){var t,n,r=xC(e,m,g);if(!Vn(m)||!(e?0<r:r<m.nodeValue.length)){if(m.parentNode===b&&s&&!e)return 1;if(e&&Hn(m)&&m===b.firstChild)return 1;if(yC(m,"TABLE")||yC(m,"HR"))return s&&!e||!s&&e;var o=new Dr(m,b);for(Vn(m)&&(e&&0===r?o.prev():e||r!==m.nodeValue.length||o.next());t=o.current();){if(Hn(t)){if(!t.getAttribute("data-mce-bogus")&&(n=t.nodeName.toLowerCase(),f[n]&&"br"!==n))return}else if(Vn(t)&&!$r(t.nodeValue))return;e?o.prev():o.next()}return 1}}function r(){u=/^(H[1-6]|PRE|FIGURE)$/.test(C)&&"HGROUP"!==x?t(p):t(),a.getParam("end_container_on_empty_block",!1)&&CC(c,y)&&c.isEmpty(b)?u=c.split(y,b):c.insertAfter(u,b),dC(a,u)}var o,u,i,s,c=a.dom,l=a.schema,f=l.getNonEmptyElements(),d=a.selection.getRng();Of(c,d).each(function(e){d.setStart(e.startContainer,e.startOffset),d.setEnd(e.endContainer,e.endOffset)});var m=d.startContainer,g=d.startOffset,p=ks(a),h=!(!e||!e.shiftKey),v=!(!e||!e.ctrlKey);Hn(m)&&m.hasChildNodes()&&(s=g>m.childNodes.length-1,m=m.childNodes[Math.min(g,m.childNodes.length-1)]||m,g=s&&Vn(m)?m.nodeValue.length:0);var b,y,C,x,w,S,p,N,E,k,_,A,R,D,T,O,B,P,L,I,M,F=wC(c,m);F&&((p&&!h||!p&&h)&&(m=function(e,t,n,r){var o,i,a,u,s,c,l=p||"P",f=e.dom,d=wC(f,n),m=f.getParent(n,f.isBlock);if(!m||!CC(f,m)){if(s=((m=m||d)===e.getBody()||(c=m)&&/^(TD|TH|CAPTION)$/.test(c.nodeName)?m:m.parentNode).nodeName.toLowerCase(),!m.hasChildNodes())return SC(e,o=f.create(l)),m.appendChild(o),t.setStart(o,0),t.setEnd(o,0),o;for(a=n;a.parentNode!==m;)a=a.parentNode;for(;a&&!f.isBlock(a);)a=(i=a).previousSibling;if(i&&e.schema.isValidChild(s,l.toLowerCase())){for(SC(e,o=f.create(l)),i.parentNode.insertBefore(o,i),a=i;a&&!f.isBlock(a);)u=a.nextSibling,o.appendChild(a),a=u;t.setStart(n,r),t.setEnd(n,r)}}return n}(a,d,m,g)),y=(b=c.getParent(m,c.isBlock))?c.getParent(b.parentNode,c.isBlock):null,C=b?b.nodeName.toUpperCase():"","LI"!==(x=y?y.nodeName.toUpperCase():"")||v||(y=(b=y).parentNode,C=x),/^(LI|DT|DD)$/.test(C)&&c.isEmpty(b)?(E=t,k=y,_=b,A=p,I=(N=a).dom,M=N.selection.getRng(),k!==N.getBody()&&(D=(A=pC(R=k)&&pC(R.parentNode)?"LI":A)?E(A):I.create("BR"),vC(k,_,!0)&&vC(k,_,!1)?gC(k,"LI")?(T=hC(k),I.insertAfter(D,T),(null===(L=(P=k).parentNode)||void 0===L?void 0:L.firstChild)===P?I.remove(T):I.remove(k)):I.replace(D,k):(vC(k,_,!0)?gC(k,"LI")?(I.insertAfter(D,hC(k)),D.appendChild(I.doc.createTextNode(" ")),D.appendChild(k)):k.parentNode.insertBefore(D,k):vC(k,_,!1)?I.insertAfter(D,hC(k)):(k=hC(k),(O=M.cloneRange()).setStartAfter(_),O.setEndAfter(k),B=O.extractContents(),"LI"===A&&(B.firstChild&&"LI"===B.firstChild.nodeName)?(D=B.firstChild,I.insertAfter(B,k)):(I.insertAfter(B,k),I.insertAfter(D,k))),I.remove(_)),dC(N,D))):p&&b===a.getBody()||(p=p||"P",Lr(b)?(u=Hr(b),c.isEmpty(b)&&bC(b),SC(a,u),dC(a,u)):n()?r():n(!0)?(u=b.parentNode.insertBefore(t(),b),dC(a,yC(b,"HR")?u:b)):((S=(w=d).cloneRange()).setStart(w.startContainer,xC(!0,w.startContainer,w.startOffset)),S.setEnd(w.endContainer,xC(!1,w.endContainer,w.endOffset)),(o=S.cloneRange()).setEndAfter(b),i=o.extractContents(),Y(qu(Et.fromDom(i),An),function(e){var t=e.dom;t.nodeValue=Eo(t.nodeValue)}),function(e){for(;Vn(e)&&(e.nodeValue=e.nodeValue.replace(/^[\r\n]+/,"")),e=e.firstChild;);}(i),u=i.firstChild,c.insertAfter(i,b),function(e,t){var n,r,o=u,i=[];if(o){for(;o=o.firstChild;){if(e.isBlock(o))return;Hn(o)&&!t[o.nodeName.toLowerCase()]&&i.push(o)}for(n=i.length;n--;)!(o=i[n]).hasChildNodes()||o.firstChild===o.lastChild&&""===o.firstChild.nodeValue?e.remove(o):(r=o)&&"A"===r.nodeName&&e.isEmpty(r)&&e.remove(o)}}(c,f),function(e,t){t.normalize();var n=t.lastChild;n&&!/^(left|right)$/gi.test(e.getStyle(n,"float",!0))||e.add(t,"br")}(c,b),c.isEmpty(b)&&bC(b),u.normalize(),c.isEmpty(u)?(c.remove(u),r()):(SC(a,u),dC(a,u))),c.setAttrib(u,"id",""),a.fire("NewBlock",{newBlock:u})))}function EC(e,t,n){var r=e.dom.createRng();n?(r.setStartBefore(t),r.setEndBefore(t)):(r.setStartAfter(t),r.setEndAfter(t)),e.selection.setRng(r),nd(e,r)}function kC(e,t){var n=Et.fromTag("br");qt(Et.fromDom(t),n),e.undoManager.add()}function _C(e,t){l1(e.getBody(),t)||$t(Et.fromDom(t),Et.fromTag("br"));var n=Et.fromTag("br");$t(Et.fromDom(t),n),EC(e,n.dom,!1),e.undoManager.add()}function AC(e){return e&&"A"===e.nodeName&&"href"in e}function RC(e){return e.fold(D,AC,AC,D)}function DC(e,t){t.fold(te,R(kC,e),R(_C,e),te)}function TC(e,t){var n,r,o,i=(r=R(bb,n=e),o=cs.fromRangeStart(n.selection.getRng()),gy(r,n.getBody(),o).filter(RC));i.isSome()?i.each(R(DC,e)):function(e,t){var n,r,o=e.selection,i=e.dom,a=o.getRng();Of(i,a).each(function(e){a.setStart(e.startContainer,e.startOffset),a.setEnd(e.endContainer,e.endOffset)});var u,s=a.startOffset,c=a.startContainer;1===c.nodeType&&c.hasChildNodes()&&(u=s>c.childNodes.length-1,c=c.childNodes[Math.min(s,c.childNodes.length-1)]||c,s=u&&3===c.nodeType?c.nodeValue.length:0);var l=i.getParent(c,i.isBlock),f=l?i.getParent(l.parentNode,i.isBlock):null,d=f?f.nodeName.toUpperCase():"",m=!(!t||!t.ctrlKey);"LI"!==d||m||(l=f),c&&3===c.nodeType&&s>=c.nodeValue.length&&!function(e){for(var t,n=new Dr(c,l),r=e.getNonEmptyElements();t=n.next();)if(r[t.nodeName.toLowerCase()]||0<t.length)return 1}(e.schema)&&(n=i.create("br"),a.insertNode(n),a.setStartAfter(n),a.setEndAfter(n),r=!0),n=i.create("br"),fs(i,a,n),EC(e,n,r),e.undoManager.add()}(e,t)}function OC(e,t){return mC(e).filter(function(e){return 0<t.length&&ze(Et.fromDom(e),t)}).isSome()}function BC(e,t){return OC(e,e.getParam("no_newline_selector",""))}function PC(n){return function(e,t){return""===ks(e)===n}}function LC(n){return function(e,t){return mC(e).filter(function(e){return vo(Et.fromDom(e))}).isSome()===n}}function IC(n,r){return function(e,t){return mC(e).fold(J(""),function(e){return e.nodeName.toUpperCase()})===n.toUpperCase()===r}}function MC(e){return IC("pre",e)}function FC(n){return function(e,t){return e.getParam("br_in_pre",!0)===n}}function UC(e,t){return OC(e,e.getParam("br_newline_selector",".mce-toc h2,figcaption,caption"))}function zC(e,t){return t}function HC(e){var t=ks(e),n=function(e,t){for(var n,r=e.getRoot(),o=t;o!==r&&"false"!==e.getContentEditable(o);)"true"===e.getContentEditable(o)&&(n=o),o=o.parentNode;return o!==r?n:r}(e.dom,e.selection.getStart());return n&&e.schema.isValidChild(n.nodeName,t||"P")}function jC(e,t){return function(n,r){return L(e,function(e,t){return e&&t(n,r)},!0)?ve.some(t):ve.none()}}function VC(e,t){var n,r;n=e,r=t,iy([jC([BC],f1.none()),jC([IC("summary",!0)],f1.br()),jC([MC(!0),FC(!1),zC],f1.br()),jC([MC(!0),FC(!1)],f1.block()),jC([MC(!0),FC(!0),zC],f1.block()),jC([MC(!0),FC(!0)],f1.br()),jC([LC(!0),zC],f1.br()),jC([LC(!0)],f1.block()),jC([PC(!0),zC,HC],f1.block()),jC([PC(!0)],f1.br()),jC([UC],f1.br()),jC([PC(!1),zC],f1.br()),jC([HC],f1.block())],[n,!(!r||!r.shiftKey)]).getOr(f1.none()).fold(function(){TC(e,t)},function(){NC(e,t)},te)}function qC(e){return e.stopImmediatePropagation()}function $C(e){return e.keyCode===If.PAGE_UP||e.keyCode===If.PAGE_DOWN}function WC(e,t,n){n&&!e.get()?t.on("NodeChange",qC,!0):!n&&e.get()&&t.off("NodeChange",qC),e.set(n)}function KC(n,r){var e=r.container(),t=r.offset();return Vn(e)?(e.insertData(t,n),ve.some(cs(e,t+n.length))):ic(r).map(function(e){var t=Et.fromText(n);return(r.isAtEnd()?$t:qt)(e,t),cs(t.dom,n.length)})}function XC(i,a){return function(e){return r=i,(!Om(o=e)&&(n=o,nf((t=r).dom,n).isNone()||tf(t.dom,n).isNone()||ip(t,n)||ap(t,n)||_m(t,n)||km(t,n)||Dm(r,o)||Tm(r,o))?g1:p1)(a);var t,n,r,o}}function YC(e){var t,n,r=cs.fromRangeStart(e.selection.getRng()),o=Et.fromDom(e.getBody());if(e.selection.isCollapsed()){var i=R(bb,e),a=cs.fromRangeStart(e.selection.getRng());return gy(i,e.getBody(),a).bind((n=o,function(e){return e.fold(function(e){return nf(n.dom,cs.before(e))},function(e){return rf(e)},function(e){return of(e)},function(e){return tf(n.dom,cs.after(e))})})).bind(XC(o,r)).exists((t=e,function(e){return t.selection.setRng(e.toRange()),t.nodeChanged(),!0}))}return!1}function GC(e){var o,i,a,u,s,t,n,r,c,l,f,d,m,g,p=w0(e);return e.on("keyup compositionstart",R(V0,e)),g=p,(m=e).on("keydown",function(e){var t,n,r,o;!1===e.isDefaultPrevented()&&(t=m,n=g,r=e,o=dt().os,eC([{keyCode:If.RIGHT,action:Z0($0,t,!0)},{keyCode:If.LEFT,action:Z0($0,t,!1)},{keyCode:If.UP,action:Z0(W0,t,!1)},{keyCode:If.DOWN,action:Z0(W0,t,!0)},{keyCode:If.RIGHT,action:Z0(lC,t,!0)},{keyCode:If.LEFT,action:Z0(lC,t,!1)},{keyCode:If.UP,action:Z0(fC,t,!1)},{keyCode:If.DOWN,action:Z0(fC,t,!0)},{keyCode:If.RIGHT,action:Z0(tC,t,!0)},{keyCode:If.LEFT,action:Z0(tC,t,!1)},{keyCode:If.UP,action:Z0(nC,t,!1)},{keyCode:If.DOWN,action:Z0(nC,t,!0)},{keyCode:If.RIGHT,action:Z0(C0,t,n,!0)},{keyCode:If.LEFT,action:Z0(C0,t,n,!1)},{keyCode:If.RIGHT,ctrlKey:!o.isOSX(),altKey:o.isOSX(),action:Z0(n1,t,n)},{keyCode:If.LEFT,ctrlKey:!o.isOSX(),altKey:o.isOSX(),action:Z0(r1,t,n)},{keyCode:If.UP,action:Z0(Q0,t,!1)},{keyCode:If.DOWN,action:Z0(Q0,t,!0)}],r).each(function(e){r.preventDefault()}))}),d=p,(f=e).on("keydown",function(e){var t,n,r;!1===e.isDefaultPrevented()&&(n=d,r=e,eC([{keyCode:If.BACKSPACE,action:Z0(M0,t=f,!1)},{keyCode:If.BACKSPACE,action:Z0(Gb,t,!1)},{keyCode:If.DELETE,action:Z0(Gb,t,!0)},{keyCode:If.BACKSPACE,action:Z0(qb,t,!1)},{keyCode:If.DELETE,action:Z0(qb,t,!0)},{keyCode:If.BACKSPACE,action:Z0(k0,t,n,!1)},{keyCode:If.DELETE,action:Z0(k0,t,n,!0)},{keyCode:If.BACKSPACE,action:Z0(yg,t,!1)},{keyCode:If.DELETE,action:Z0(yg,t,!0)},{keyCode:If.BACKSPACE,action:Z0(Jb,t,!1)},{keyCode:If.DELETE,action:Z0(Jb,t,!0)},{keyCode:If.BACKSPACE,action:Z0(T0,t,!1)},{keyCode:If.DELETE,action:Z0(T0,t,!0)},{keyCode:If.BACKSPACE,action:Z0(Ib,t,!1)},{keyCode:If.DELETE,action:Z0(Ib,t,!0)},{keyCode:If.BACKSPACE,action:Z0(Bb,t,!1)},{keyCode:If.DELETE,action:Z0(Bb,t,!0)},{keyCode:If.BACKSPACE,action:Z0(R0,t,!1)},{keyCode:If.DELETE,action:Z0(R0,t,!0)}],r).each(function(e){r.preventDefault()}))}),f.on("keyup",function(e){var t,n;!1===e.isDefaultPrevented()&&(n=e,eC([{keyCode:If.BACKSPACE,action:Z0(Yb,t=f)},{keyCode:If.DELETE,action:Z0(Yb,t)}],n))}),(l=e).on("keydown",function(e){var t,n,r;e.keyCode===If.ENTER&&(t=l,(n=e).isDefaultPrevented()||(n.preventDefault(),(r=t.undoManager).typing&&(r.typing=!1,r.add()),t.undoManager.transact(function(){!1===t.selection.isCollapsed()&&t.execCommand("Delete"),VC(t,n)})))}),(c=e).on("keydown",function(e){var t;!1===e.isDefaultPrevented()&&(t=e,eC([{keyCode:If.SPACEBAR,action:Z0(YC,c)}],t).each(function(e){t.preventDefault()}))}),n=t=e,r=mu(function(){n.composing||Um(n)},0),d1.isIE()&&(n.on("keypress",function(e){r.throttle()}),n.on("remove",function(e){r.cancel()})),t.on("input",function(e){!1===e.isComposing&&Um(t)}),s=p,(u=e).on("keydown",function(e){var t,n,r;!1===e.isDefaultPrevented()&&(n=s,r=e,eC([{keyCode:If.END,action:Z0(K0,t=u,!0)},{keyCode:If.HOME,action:Z0(K0,t,!1)},{keyCode:If.END,action:Z0(rC,t,!0)},{keyCode:If.HOME,action:Z0(rC,t,!1)},{keyCode:If.END,action:Z0(S0,t,!0,n)},{keyCode:If.HOME,action:Z0(S0,t,!1,n)}],r).each(function(e){r.preventDefault()}))}),o=e,i=p,m1.os.isOSX()||(a=au(!1),o.on("keydown",function(e){$C(e)&&WC(a,o,!0)}),o.on("keyup",function(e){var t,n,r;!1===e.isDefaultPrevented()&&(r=e,eC([{keyCode:If.PAGE_UP,action:Z0(S0,t=o,!1,n=i)},{keyCode:If.PAGE_DOWN,action:Z0(S0,t,!0,n)}],r)),$C(e)&&a.get()&&(WC(a,o,!1),o.nodeChanged())})),p}(Jy=Gy=Gy||{})[Jy.Up=-1]="Up",Jy[Jy.Down=1]="Down";var JC=R(n0,Gy.Up,Ou,Bu),QC=R(n0,Gy.Down,Bu,Ou),ZC=Gn,e1=Gs,t1=function(e,t){var n=e.selection.getRng(),r=e.getBody();if(t){var o=cs.fromRangeEnd(n),i=Zy(r,o);return Z(i.positions)}return o=cs.fromRangeStart(n),Q((i=Qy(r,o)).positions)},n1=R(x0,!0),r1=R(x0,!1),o1=function(e){return U(A(e.selection.getSelectedBlocks(),Et.fromDom),function(e){return!L0(e)&&!Ot(e).exists(L0)&&hr(e,function(e){return Yn(e.dom)||Gn(e.dom)}).exists(function(e){return Yn(e.dom)})})},i1=Gn,a1=R(oC,function(e){return e.bottom},function(e,t){return e.y<t}),u1=R(oC,function(e){return e.top},function(e,t){return e.y>t}),s1=R(iC,Qy),c1=R(iC,Zy),l1=function(e,t){return n=cs.after(t),!!Kn(n.getNode())||tf(e,cs.after(t)).map(function(e){return Kn(e.getNode())}).getOr(!1);var n},f1=ir([{br:[]},{block:[]},{none:[]}]),d1=dt().browser,m1=dt(),g1=R(KC,wo),p1=R(KC," "),h1=(v1.prototype.nodeChanged=function(e){var t,n,r,o=this.editor.selection;this.editor.initialized&&o&&!this.editor.getParam("disable_nodechange")&&!this.editor.mode.isReadOnly()&&(r=this.editor.getBody(),(t=o.getStart(!0)||r).ownerDocument===this.editor.getDoc()&&this.editor.dom.isChildOf(t,r)||(t=r),n=[],this.editor.dom.getParent(t,function(e){return e===r||void n.push(e)}),(e=e||{}).element=t,e.parents=n,this.editor.fire("NodeChange",e))},v1.prototype.isSameElementPath=function(e){var t,n=this.editor.$(e).parentsUntil(this.editor.getBody()).add(e);if(n.length===this.lastPath.length){for(t=n.length;0<=t&&n[t]===this.lastPath[t];t--);if(-1===t)return this.lastPath=n,!0}return this.lastPath=n,!1},v1);function v1(r){var o;this.lastPath=[],this.editor=r;var t=this;"onselectionchange"in r.getDoc()||r.on("NodeChange click mouseup keyup focus",function(e){var t=r.selection.getRng(),n={startContainer:t.startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset};"nodechange"!==e.type&&kf(n,o)||r.fire("SelectionChange"),o=n}),r.on("contextmenu",function(){r.fire("SelectionChange")}),r.on("SelectionChange",function(){var e=r.selection.getStart(!0);!e||!xt.range&&r.selection.isCollapsed()||Pl(r)&&!t.isSameElementPath(e)&&r.dom.isChildOf(e,r.getBody())&&r.nodeChanged({selectionChange:!0})}),r.on("mouseup",function(e){!e.isDefaultPrevented()&&Pl(r)&&("IMG"===r.selection.getNode().nodeName?Ar.setEditorTimeout(r,function(){r.nodeChanged()}):r.nodeChanged())})}function b1(e){return Hn(e)&&po(Et.fromDom(e))}function y1(e){var t=e.getBoundingClientRect(),n=e.ownerDocument,r=n.documentElement,o=n.defaultView;return{top:t.top+o.pageYOffset-r.clientTop,left:t.left+o.pageXOffset-r.clientLeft}}function C1(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function x1(e,S){var N=Ar.throttle(function(e,t){S._selectionOverrides.hideFakeCaret(),S.selection.placeCaretAt(e,t)},0);return S.on("remove",N.stop),function(w){return e.on(function(e){var t,n,r,o,i,a,u,s,c,l,f,d,m,g,p,h,v,b,y,C,x=Math.max(Math.abs(w.screenX-e.screenX),Math.abs(w.screenY-e.screenY));if(!e.dragging&&10<x){if(S.fire("dragstart",{target:e.element}).isDefaultPrevented())return;e.dragging=!0,S.focus()}e.dragging&&(d=e,t={pageX:(p=w,h=(g=S).inline?y1(g.getBody()):{left:0,top:0},C=(y=g).getBody(),v=y.inline?{left:C.scrollLeft,top:C.scrollTop}:{left:0,top:0},(m={pageX:(b=function(e,t){if(t.target.ownerDocument===e.getDoc())return{left:t.pageX,top:t.pageY};var n,r,o,i,a,u=y1(e.getContentAreaContainer()),s=(r=(n=e).getBody(),o=n.getDoc().documentElement,i={left:r.scrollLeft,top:r.scrollTop},a={left:r.scrollLeft||o.scrollLeft,top:r.scrollTop||o.scrollTop},n.inline?i:a);return{left:t.pageX-u.left+s.left,top:t.pageY-u.top+s.top}}(g,p)).left-h.left+v.left,pageY:b.top-h.top+v.top}).pageX-d.relX),pageY:m.pageY+5},l=e.ghost,f=S.getBody(),l.parentNode!==f&&f.appendChild(l),n=e.ghost,o=e.width,i=e.height,a=e.maxX,u=e.maxY,c=s=0,n.style.left=(r=t).pageX+"px",n.style.top=r.pageY+"px",u<r.pageY+i&&(c=r.pageY+i-u),n.style.width=o-(s=a<r.pageX+o?r.pageX+o-a:s)+"px",n.style.height=i-c+"px",N(w.clientX,w.clientY))})}}function w1(e){function t(e){var t,n,r,o,i,a;0===e.button&&(t=M(c.dom.getParents(e.target),function(){for(var n=[],e=0;e<arguments.length;e++)n[e]=arguments[e];return function(e){for(var t=0;t<n.length;t++)if(n[t](e))return!0;return!1}}(K1,X1)).getOr(null),i=c.getBody(),K1(a=t)&&a!==i&&(n=c.dom.getPos(t),r=c.getBody(),o=c.getDoc().documentElement,u.set({element:t,dragging:!1,screenX:e.screenX,screenY:e.screenY,maxX:(c.inline?r.scrollWidth:o.offsetWidth)-2,maxY:(c.inline?r.scrollHeight:o.offsetHeight)-2,relX:e.pageX-n.x,relY:e.pageY-n.y,width:t.offsetWidth,height:t.offsetHeight,ghost:function(e,t,n){var r=c.dom,o=e.cloneNode(!0);r.setStyles(o,{width:t,height:n}),r.setAttrib(o,"data-mce-selected",null);var i=r.create("div",{class:"mce-drag-container","data-mce-bogus":"all",unselectable:"on",contenteditable:"false"});return r.setStyles(i,{position:"absolute",opacity:.5,overflow:"hidden",border:0,padding:0,margin:0,width:t,height:n}),r.setStyles(o,{margin:0,boxSizing:"border-box"}),i.appendChild(o),i}(t,t.offsetWidth,t.offsetHeight)})))}function n(u){i.on(function(e){var t,n,r,o,i,a;e.dragging&&((o=3===(a=(r=s).selection.getSel().getRangeAt(0).startContainer).nodeType?a.parentNode:a)===(i=e.element)||r.dom.isChildOf(o,i)||K1(o)||((n=e.element.cloneNode(!0)).removeAttribute("data-mce-selected"),t=n,s.fire("drop",{clientX:u.clientX,clientY:u.clientY}).isDefaultPrevented()||s.undoManager.transact(function(){C1(e.element),s.insertContent(s.dom.getOuterHTML(t)),s._selectionOverrides.hideFakeCaret()})),s.fire("dragend"))}),Y1(i)}var r,o,i,s,u,c,a=du(),l=eu.DOM,f=document,d=x1(u=a,c=e),m=(r=i=a,function(){r.on(function(e){e.dragging&&o.fire("dragend")}),Y1(r)});(o=s=e).on("mousedown",t),e.on("mousemove",d),e.on("mouseup",n),l.bind(f,"mousemove",d),l.bind(f,"mouseup",m),e.on("remove",function(){l.unbind(f,"mousemove",d),l.unbind(f,"mouseup",m)}),e.on("keydown",function(e){e.keyCode===If.ESC&&m()})}function S1(e){var n,i;function a(e){var t;e.isDefaultPrevented()||(t=e.dataTransfer)&&(T(t.types,"Files")||0<t.files.length)&&(e.preventDefault(),"drop"===e.type&&Qv(i,"Dropped file type is not supported"))}function u(e){pd(i,e.target)&&a(e)}function t(){var t=eu.DOM,n=i.dom,r=document,o=i.inline?i.getBody():i.getDoc(),e=["drop","dragover"];Y(e,function(e){t.bind(r,e,u),n.bind(o,e,a)}),i.on("remove",function(){Y(e,function(e){t.unbind(r,e,u),n.unbind(o,e,a)})})}w1(e),(n=e).on("drop",function(e){var t=void 0!==e.clientX?n.getDoc().elementFromPoint(e.clientX,e.clientY):null;!K1(t)&&"false"!==n.dom.getContentEditableParent(t)||e.preventDefault()}),e.getParam("block_unsupported_drop",!0,"boolean")&&(i=e).on("init",function(){Ar.setEditorTimeout(i,t,0)})}function N1(e,t){return bf(e.getBody(),t)}function E1(l){function f(e){return e!==x&&(J1(e)||Qn(e))&&y.isChildOf(e,x)}function c(e){return rp(e)||op(e)||Zg(e)||ep(e)}function d(e){e&&b.setRng(e)}function m(e,t,n,r){return void 0===r&&(r=!0),l.fire("ShowCaret",{target:t,direction:e,before:n}).isDefaultPrevented()?null:(r&&b.scrollIntoView(t,-1===e),i.show(n,t))}function t(e){return Mr(e)||Ao(e)||Ro(e)}function g(e){return t(e.startContainer)||t(e.endContainer)}function p(e,t){if(!e)return null;if(e.collapsed){if(!g(e)){var n=t?1:-1,r=oc(n,x,e),o=r.getNode(!t);if(Xs(o))return m(n,o,!!t&&!r.isAtEnd(),!1);var i=r.getNode(t);if(Xs(i))return m(n,i,!t&&!r.isAtEnd(),!1)}return null}var a=e.startContainer,u=e.startOffset,s=e.endOffset;if(3===a.nodeType&&0===u&&J1(a.parentNode)&&(a=a.parentNode,u=y.nodeIndex(a),a=a.parentNode),1!==a.nodeType)return null;if(s===u+1&&a===e.endContainer){var c=a.childNodes[u];if(f(c))return function(e){var t=e.cloneNode(!0),n=l.fire("ObjectSelected",{target:e,targetClone:t});if(n.isDefaultPrevented())return null;var r=function(e,t,n){var r=l.$,o=br(Et.fromDom(l.getBody()),"#"+w).fold(function(){return r([])},function(e){return r([e.dom])});0===o.length&&(o=r('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>').attr("id",w)).appendTo(l.getBody());var i=y.createRng();t===n&&xt.ie?(o.empty().append('<p style="font-size: 0" data-mce-bogus="all">\xa0</p>').append(t),i.setStartAfter(o[0].firstChild.firstChild),i.setEndAfter(t)):(o.empty().append(wo).append(t).append(wo),i.setStart(o[0].firstChild,1),i.setEnd(o[0].lastChild,0)),o.css({top:y.getPos(e,l.getBody()).y}),o[0].focus();var a=b.getSel();return a.removeAllRanges(),a.addRange(i),i}(e,n.targetClone,t),o=Et.fromDom(e);return Y(yu(Et.fromDom(l.getBody()),"*[data-mce-selected]"),function(e){je(o,e)||Cn(e,S)}),y.getAttrib(e,S)||e.setAttribute(S,"1"),v=e,N(),r}(c)}return null}function h(){v&&v.removeAttribute(S),br(Et.fromDom(l.getBody()),"#"+w).each(In),v=null}var v,n,e,o,b=l.selection,y=l.dom,C=y.isBlock,x=l.getBody(),i=Ws(l,x,C,function(){return Cd(l)}),w="sel-"+y.uniqueId(),S="data-mce-selected",r=b.getRng,N=function(){i.hide()};return xt.ceFalse&&!hh(l)&&(l.on("mouseup",function(e){var t=r();t.collapsed&&Nv(l,e.clientX,e.clientY)&&Ub(l,t,!1).each(d)}),l.on("click",function(e){var t=N1(l,e.target);t&&(J1(t)&&(e.preventDefault(),l.focus()),G1(t)&&y.isChildOf(t,b.getNode())&&h())}),l.on("blur NewBlock",h),l.on("ResizeWindow FullscreenStateChanged",i.reposition),l.on("tap",function(e){var t=e.target,n=N1(l,t);J1(n)?(e.preventDefault(),Fb(l,n).each(p)):f(t)&&Fb(l,t).each(p)},!0),l.on("mousedown",function(e){var t,n,r,o,i,a,u,s=e.target;s!==x&&"HTML"!==s.nodeName&&!y.isChildOf(s,x)||!1===Nv(l,e.clientX,e.clientY)||((t=N1(l,s))?J1(t)?(e.preventDefault(),Fb(l,t).each(p)):(h(),G1(t)&&e.shiftKey||yf(e.clientX,e.clientY,b.getRng())||(N(),b.placeCaretAt(e.clientX,e.clientY))):f(s)?Fb(l,s).each(p):!1===Xs(s)&&(h(),N(),(n=f0(x,e.clientX,e.clientY))&&(r=s,o=n.node,a=y.getParent(r,C),u=y.getParent(o,C),!K(a)&&(r!==u&&y.isChildOf(a,u)&&!1===J1(N1(l,a))||!y.isChildOf(u,a)&&(i=u,y.getParent(a,C)!==y.getParent(i,C))&&function(e){var t=e.firstChild;if(!K(t)){var n=cs.before(t);if(Kn(n.getNode())&&1===e.childNodes.length)return!c(n);var r=Mc(e).next(n);return r&&!c(r)}}(a))||(e.preventDefault(),d(m(1,n.node,n.before,!1)),l.getBody().focus()))))}),l.on("keypress",function(e){If.modifierPressed(e)||J1(b.getNode())&&e.preventDefault()}),l.on("GetSelectionRange",function(e){var t=e.range;v&&(v.parentNode?((t=t.cloneRange()).selectNode(v),e.range=t):v=null)}),l.on("SetSelectionRange",function(e){var t,n,r,o,i,a,u;e.range=(t=e.range,n=l.schema.getShortEndedElements(),r=y.createRng(),o=t.startContainer,i=t.startOffset,a=t.endContainer,u=t.endOffset,Ee(n,o.nodeName.toLowerCase())?0===i?r.setStartBefore(o):r.setStartAfter(o):r.setStart(o,i),Ee(n,a.nodeName.toLowerCase())?0===u?r.setEndBefore(a):r.setEndAfter(a):r.setEnd(a,u),r);var s=p(e.range,e.forward);s&&(e.range=s)}),l.on("AfterSetSelectionRange",function(e){var t=e.range,n=t.startContainer.parentNode;g(t)||"mcepastebin"===n.id||N(),y.hasClass(n,"mce-offscreen-selection")||h()}),l.on("copy",function(e){var t,n,r=e.clipboardData;e.isDefaultPrevented()||!e.clipboardData||xt.ie||(t=(n=y.get(w))&&n.getElementsByTagName("*")[0])&&(e.preventDefault(),r.clearData(),r.setData("text/html",t.outerHTML),r.setData("text/plain",t.outerText||t.innerText))}),S1(l),e=mu(function(){var e,t;n.removed||!n.getBody().contains(document.activeElement)||(e=n.selection.getRng()).collapsed&&(t=zb(n,e,!1),n.selection.setRng(t))},0),(n=l).on("focus",function(){e.throttle()}),n.on("blur",function(){e.cancel()}),(o=l).on("init",function(){o.on("focusin",function(e){var t,n,r=e.target;Qn(r)&&(t=bf(o.getBody(),r),n=Gn(t)?t:r,o.selection.getNode()!==n&&Fb(o,n).each(function(e){return o.selection.setRng(e)}))})})),{showCaret:m,showBlockCaretContainer:function(e){e.hasAttribute("data-mce-caret")&&(Hr(e),d(r()),b.scrollIntoView(e))},hideFakeCaret:N,destroy:function(){i.destroy(),v=null}}}function k1(a){function e(e,t){try{a.getDoc().execCommand(e,!1,t)}catch(e){}}function u(e){return e.isDefaultPrevented()}function t(){a.shortcuts.add("meta+a",null,"SelectAll")}function n(){a.inline||b.bind(a.getDoc(),"mousedown mouseup",function(e){var t;e.target===a.getDoc().documentElement&&(t=y.getRng(),a.getBody().focus(),"mousedown"===e.type?Mr(t.startContainer)||y.placeCaretAt(e.clientX,e.clientY):y.setRng(t))})}function r(){Range.prototype.getClientRects||a.on("mousedown",function(e){var t;u(e)||"HTML"!==e.target.nodeName||((t=a.getBody()).blur(),Ar.setEditorTimeout(a,function(){t.focus()}))})}function o(){a.on("click",function(e){var t=e.target;/^(IMG|HR)$/.test(t.nodeName)&&"false"!==b.getContentEditableParent(t)&&(e.preventDefault(),a.selection.select(t),a.nodeChanged()),"A"===t.nodeName&&b.hasClass(t,"mce-item-anchor")&&(e.preventDefault(),y.select(t))})}function i(){a.on("keydown",function(e){if(!u(e)&&e.keyCode===h&&y.isCollapsed()&&0===y.getRng().startOffset){var t=y.getNode().previousSibling;if(t&&t.nodeName&&"table"===t.nodeName.toLowerCase())return e.preventDefault(),!1}})}function s(){a.getParam("readonly")||a.on("BeforeExecCommand mousedown",function(){e("StyleWithCSS",!1),e("enableInlineTableEditing",!1),Ps(a)||e("enableObjectResizing",!1)})}function c(){a.contentStyles.push("img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}")}function l(){a.inline||a.on("keydown",function(){document.activeElement===document.body&&a.getWin().focus()})}function f(){a.inline||(a.contentStyles.push("body {min-height: 150px}"),a.on("click",function(e){var t;"HTML"===e.target.nodeName&&(11<xt.ie?a.getBody().focus():(t=a.selection.getRng(),a.getBody().focus(),a.selection.setRng(t),a.selection.normalize(),a.nodeChanged()))}))}function d(){xt.mac&&a.on("keydown",function(e){!If.metaKeyPressed(e)||e.shiftKey||37!==e.keyCode&&39!==e.keyCode||(e.preventDefault(),a.selection.getSel().modify("move",37===e.keyCode?"backward":"forward","lineboundary"))})}function m(){a.on("click",function(e){var t=e.target;do{if("A"===t.tagName)return void e.preventDefault()}while(t=t.parentNode)}),a.contentStyles.push(".mce-content-body {-webkit-touch-callout: none}")}function g(){a.on("init",function(){a.dom.bind(a.getBody(),"submit",function(e){e.preventDefault()})})}var p=Nt.each,h=If.BACKSPACE,v=If.DELETE,b=a.dom,y=a.selection,C=a.parser,x=xt.gecko,w=xt.ie,S=xt.webkit,N="data:text/mce-internal,",E=w?"Text":"URL",k=te;return hh(a)?(S&&(n(),o(),g(),t(),xt.iOS&&(l(),f(),m())),x&&(r(),s(),c(),d())):(a.on("keydown",function(e){if(!u(e)&&e.keyCode===If.BACKSPACE){var t,n=(t=y.getRng()).startContainer,r=t.startOffset,o=b.getRoot(),i=n;if(t.collapsed&&0===r){for(;i&&i.parentNode&&i.parentNode.firstChild===i&&i.parentNode!==o;)i=i.parentNode;"BLOCKQUOTE"===i.tagName&&(a.formatter.toggle("blockquote",null,i),(t=b.createRng()).setStart(n,0),t.setEnd(n,0),y.setRng(t))}}}),a.on("keydown",function(e){var t,n,r,o,i=e.keyCode;u(e)||i!==v&&i!==h||(t=a.selection.isCollapsed(),n=a.getBody(),t&&!b.isEmpty(n)||!t&&(r=R(a.selection.getRng()),(o=b.createRng()).selectNode(a.getBody()),r!==R(o))||(e.preventDefault(),a.setContent(""),n.firstChild&&b.isBlock(n.firstChild)?a.selection.setCursorLocation(n.firstChild,0):a.selection.setCursorLocation(n,0),a.nodeChanged()))}),xt.windowsPhone||a.on("keyup focusin mouseup",function(e){If.modifierPressed(e)||y.normalize()},!0),S&&(n(),o(),ks(a)&&a.on("init",function(){e("DefaultParagraphSeparator",ks(a))}),g(),i(),C.addNodeFilter("br",function(e){for(var t=e.length;t--;)"Apple-interchange-newline"===e[t].attr("class")&&e[t].remove()}),xt.iOS?(l(),f(),m()):t()),11<=xt.ie&&(f(),i()),xt.ie&&(t(),e("AutoUrlDetect",!1),a.on("dragstart",function(e){var t,n,r;(t=e).dataTransfer&&(a.selection.isCollapsed()&&"IMG"===t.target.tagName&&y.select(t.target),0<(n=a.selection.getContent()).length&&(r=N+escape(a.id)+","+escape(n),t.dataTransfer.setData(E,r)))}),a.on("drop",function(e){var t,n,r,o;u(e)||(t=e.dataTransfer&&(o=e.dataTransfer.getData(E))&&0<=o.indexOf(N)?(o=o.substr(N.length).split(","),{id:unescape(o[0]),html:unescape(o[1])}):null)&&t.id!==a.id&&(e.preventDefault(),n=Ef(e.x,e.y,a.getDoc()),y.setRng(n),r=t.html,a.queryCommandSupported("mceInsertClipboardContent")?a.execCommand("mceInsertClipboardContent",!1,{content:r,internal:!0}):a.execCommand("mceInsertContent",!1,r))})),x&&(a.on("keydown",function(e){if(!u(e)&&e.keyCode===h&&a.getBody().getElementsByTagName("hr").length&&y.isCollapsed()&&0===y.getRng().startOffset){var t=y.getNode(),n=t.previousSibling;if("HR"===t.nodeName)return b.remove(t),void e.preventDefault();n&&n.nodeName&&"hr"===n.nodeName.toLowerCase()&&(b.remove(n),e.preventDefault())}}),r(),a.on("keypress",function(e){var t;if(!u(e)&&(8===e.keyCode||46===e.keyCode)&&A())return t=_(),a.getDoc().execCommand("delete",!1,null),t(),e.preventDefault(),!1}),b.bind(a.getDoc(),"cut",function(e){var t;!u(e)&&A()&&(t=_(),Ar.setEditorTimeout(a,function(){t()}))}),s(),a.on("SetContent ExecCommand",function(e){"setcontent"!==e.type&&"mceInsertLink"!==e.command||p(b.select("a"),function(e){var t=e.parentNode,n=b.getRoot();if(t.lastChild===e){for(;t&&!b.isBlock(t);){if(t.parentNode.lastChild!==t||t===n)return;t=t.parentNode}b.add(t,"br",{"data-mce-bogus":1})}})}),c(),d(),i())),{refreshContentEditable:k,isHidden:function(){if(!x||a.removed)return!1;var e=a.selection.getSel();return!e||!e.rangeCount||0===e.rangeCount}};function _(){var e=b.getAttribs(y.getStart().cloneNode(!1));return function(){var t=y.getStart();t!==a.getBody()&&(b.setAttrib(t,"style",null),p(e,function(e){t.setAttributeNode(e.cloneNode(!0))}))}}function A(){return!y.isCollapsed()&&b.getParent(y.getStart(),b.isBlock)!==b.getParent(y.getEnd(),b.isBlock)}function R(e){var t=b.create("body"),n=e.cloneContents();return t.appendChild(n),y.serializer.serialize(t,{format:"html"})}}function _1(e){return ae(e,function(e){return!1===b(e)})}function A1(e){var t=e.settings;return _1({block_elements:t.block_elements,boolean_attributes:t.boolean_attributes,custom_elements:t.custom_elements,extended_valid_elements:t.extended_valid_elements,invalid_elements:t.invalid_elements,invalid_styles:t.invalid_styles,move_caret_before_on_enter_elements:t.move_caret_before_on_enter_elements,non_empty_elements:t.non_empty_elements,schema:t.schema,self_closing_elements:t.self_closing_elements,short_ended_elements:t.short_ended_elements,special:t.special,text_block_elements:t.text_block_elements,text_inline_elements:t.text_inline_elements,valid_children:t.valid_children,valid_classes:t.valid_classes,valid_elements:t.valid_elements,valid_styles:t.valid_styles,verify_html:t.verify_html,whitespace_elements:t.whitespace_elements,padd_empty_block_inline_children:t.format_empty_lines})}function R1(e){var t=e.settings,n=e.editorUpload.blobCache;return _1({allow_conditional_comments:t.allow_conditional_comments,allow_html_data_urls:t.allow_html_data_urls,allow_svg_data_urls:t.allow_svg_data_urls,allow_html_in_named_anchor:t.allow_html_in_named_anchor,allow_script_urls:t.allow_script_urls,allow_unsafe_link_target:t.allow_unsafe_link_target,convert_fonts_to_spans:t.convert_fonts_to_spans,fix_list_elements:t.fix_list_elements,font_size_legacy_values:t.font_size_legacy_values,forced_root_block:t.forced_root_block,forced_root_block_attrs:t.forced_root_block_attrs,padd_empty_with_br:t.padd_empty_with_br,preserve_cdata:t.preserve_cdata,remove_trailing_brs:t.remove_trailing_brs,inline_styles:t.inline_styles,root_name:e.inline?e.getElement().nodeName.toLowerCase():void 0,validate:!0,blob_cache:n,document:e.getDoc(),images_dataimg_filter:t.images_dataimg_filter})}function D1(e){var t,u,n;e.bindPendingEventDelegates(),e.initialized=!0,e.fire("Init"),e.focus(!0),n=(u=e).dom.getRoot(),u.inline||Pl(u)&&u.selection.getStart(!0)!==n||rf(n).each(function(e){var t,n,r,o,i=e.getNode(),a=cn(i)?rf(i).getOr(e):e;xt.browser.isIE()?(t=u,n=a.toRange(),r=Et.fromDom(t.getBody()),o=(cd(t)?ve.from(n):ve.none()).map(ld).filter(sd(r)),t.bookmark=o.isSome()?o:t.bookmark):u.selection.setRng(a.toRange())}),e.nodeChanged({initial:!0}),e.execCallback("init_instance_callback",e),(t=e).settings.auto_focus&&Ar.setEditorTimeout(t,function(){var e=!0===t.settings.auto_focus?t:t.editorManager.get(t.settings.auto_focus);e.destroyed||e.focus()},100)}function T1(e){return(e.inline?e.ui:e.dom).styleSheetLoader}function O1(e){function t(){o.unloadAll(a),e.inline||e.ui.styleSheetLoader.unloadAll(i)}function n(){e.removed?t():e.on("remove",t)}var r,o=T1(e),i=Bs(e),a=e.contentCSS;0<e.contentStyles.length&&(r="",Nt.each(e.contentStyles,function(e){r+=e+"\r\n"}),e.dom.addStyle(r));var u,s,c,l,f,d,m,g,p,h=_r.all((u=e,s=a,c=i,l=[new _r(function(e,t){return T1(u).loadAll(s,e,t)})],u.inline?l:l.concat([new _r(function(e,t){return u.ui.styleSheetLoader.loadAll(c,e,t)})]))).then(n).catch(n);return e.settings.content_style&&(d=(f=e).settings.content_style,m=Et.fromDom(f.getBody()),g=jt(Pn(m)),pn(p=Et.fromTag("style"),"type","text/css"),Ln(p,Et.fromText(d)),Ln(g,p),f.on("remove",function(){In(p)})),h}function B1(e){var t;!0!==e.removed&&(hh(t=e)||t.load({initial:!0,format:"html"}),t.startContent=t.getContent({format:"raw"}),D1(e))}function P1(t,e){var n=t.settings,r=t.getElement(),o=t.getDoc();n.inline||(t.getElement().style.visibility=t.orgVisibility),e||t.inline||(o.open(),o.write(t.iframeHTML),o.close()),t.inline&&(Q1.addClass(r,"mce-content-body"),t.contentDocument=o=document,t.contentWindow=window,t.bodyElement=r,t.contentAreaContainer=r);var u,i,a,s,c,l,f,d,m,g,p,h,v=t.getBody();v.disabled=!0,t.readonly=!!n.readonly,t.readonly||(t.inline&&"static"===Q1.getStyle(v,"position",!0)&&(v.style.position="relative"),v.contentEditable=t.getParam("content_editable_state",!0)),v.disabled=!1,t.editorUpload=cb(t),t.schema=oo(A1(t)),t.dom=eu(o,{keep_values:!0,url_converter:t.convertURL,url_converter_scope:t,hex_colors:n.force_hex_style_colors,update_styles:!0,root_element:t.inline?t.getBody():null,collect:function(){return t.inline},schema:t.schema,contentCssCors:t.getParam("content_css_cors",!1,"boolean"),referrerPolicy:Ds(t),onSetAttrib:function(e){t.fire("SetAttrib",e)}}),t.parser=((i=cv(R1(u=t),u.schema)).addAttributeFilter("src,href,style,tabindex",function(e,t){for(var n,r,o=e.length,i=u.dom,a="data-mce-"+t;o--;)(r=(n=e[o]).attr(t))&&!n.attr(a)&&0!==r.indexOf("data:")&&0!==r.indexOf("blob:")&&("style"===t?((r=i.serializeStyle(i.parseStyle(r),n.name)).length||(r=null),n.attr(a,r),n.attr(t,r)):"tabindex"===t?(n.attr(a,r),n.attr(t,null)):n.attr(a,u.convertURL(r,t,n.name)))}),i.addNodeFilter("script",function(e){for(var t=e.length;t--;){var n=e[t],r=n.attr("type")||"no/type";0!==r.indexOf("mce-")&&n.attr("type","mce-"+r)}}),u.settings.preserve_cdata&&i.addNodeFilter("#cdata",function(e){for(var t=e.length;t--;){var n=e[t];n.type=8,n.name="#comment",n.value="[CDATA["+u.dom.encode(n.value)+"]]"}}),i.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(e){for(var t=e.length,n=u.schema.getNonEmptyElements();t--;){var r=e[t];r.isEmpty(n)&&0===r.getAll("br").length&&(r.append(new jd("br",1)).shortEnded=!0)}}),i),t.serializer=dv((s=(a=t).settings,_e(_e(_e({},R1(a)),A1(a)),_1({url_converter:s.url_converter,url_converter_scope:s.url_converter_scope,element_format:s.element_format,entities:s.entities,entity_encoding:s.entity_encoding,indent:s.indent,indent_after:s.indent_after,indent_before:s.indent_before}))),t),t.selection=Fh(t.dom,t.getWin(),t.serializer,t),t.annotator=zl(t),t.formatter=mb(t),t.undoManager=pb(t),t._nodeChangeDispatcher=new h1(t),t._selectionOverrides=E1(t),m=t,g=du(),p=au(!1),h=gu(function(e){m.fire("longpress",_e(_e({},e),{type:"longpress"})),p.set(!0)},400),m.on("touchstart",function(n){U0(n).each(function(e){h.cancel();var t={x:e.clientX,y:e.clientY,target:n.target};h.throttle(n),p.set(!1),g.set(t)})},!0),m.on("touchmove",function(e){h.cancel(),U0(e).each(function(i){g.on(function(e){var t=i,n=e,r=Math.abs(t.clientX-n.x),o=Math.abs(t.clientY-n.y);(5<r||5<o)&&(g.clear(),p.set(!1),m.fire("longpresscancel"))})})},!0),m.on("touchend touchcancel",function(t){h.cancel(),"touchcancel"!==t.type&&g.get().filter(function(e){return e.target.isEqualNode(t.target)}).each(function(){p.get()?t.preventDefault():m.fire("tap",_e(_e({},t),{type:"tap"}))})},!0),(f=l=t).on("click",function(e){f.dom.getParent(e.target,"details")&&e.preventDefault()}),(d=l).parser.addNodeFilter("details",function(e){Y(e,function(e){e.attr("data-mce-open",e.attr("open")),e.attr("open","open")})}),d.serializer.addNodeFilter("details",function(e){Y(e,function(e){var t=e.attr("data-mce-open");e.attr("open",X(t)?t:null),e.attr("data-mce-open",null)})}),hh(t)||(c=t).on("click",function(e){var t,n,r,o,i;3<=e.detail&&(r=(t=c).selection.getRng(),o=cs.fromRangeStart(r),i=cs.fromRangeEnd(r),!cs.isElementPosition(o)||b1(n=o.container())&&rf(n).each(function(e){return r.setStart(e.container(),e.offset())}),!cs.isElementPosition(i)||b1(n=o.container())&&of(n).each(function(e){return r.setEnd(e.container(),e.offset())}),t.selection.setRng(Cg(r)))});var b,y,C,x,w,S,N,E,k,_=hh(b=t)?au(null):GC(b);k=_,(E=t).addCommand("delete",function(){var e,t=k;M0(e=E)||Gb(e,!1)||qb(e,!1)||k0(e,t,!1)||Bb(e,!1)||yg(e)||Jb(e,!1)||T0(e,!1)||Ib(e)||R0(e,!1)||(F0(e,"Delete"),Sb(e))}),E.addCommand("forwardDelete",function(){var e,t=k;Gb(e=E,!0)||qb(e,!0)||k0(e,t,!0)||Bb(e,!0)||yg(e)||Jb(e,!0)||T0(e,!0)||Ib(e)||R0(e,!0)||F0(e,"ForwardDelete")}),ks(y=t)&&y.on("NodeChange",R(H0,y)),x=(C=t).dom,w=ks(C),S=C.getParam("placeholder",vc.getAttrib(C.getElement(),"placeholder"),"string"),N=function(e,t){var n,r,o;!function(e){if(hb(e)){var t=e.keyCode;return!vb(e)&&(If.metaKeyPressed(e)||e.altKey||112<=t&&t<=123||T(Ry,t))}}(e)&&(n=C.getBody(),r=!(hb(o=e)&&!(vb(o)||"keyup"===o.type&&229===o.keyCode))&&function(e,t,n){if(Kr(Et.fromDom(t),!1)){var r=""===n,o=t.firstElementChild;return!o||!e.getStyle(t.firstElementChild,"padding-left")&&!e.getStyle(t.firstElementChild,"padding-right")&&(r?!e.isBlock(o):n===o.nodeName.toLowerCase())}return!1}(x,n,w),""!==x.getAttrib(n,Dy)===r&&!t||(x.setAttrib(n,Dy,r?S:null),x.setAttrib(n,"aria-placeholder",r?S:null),C.fire("PlaceholderToggle",{state:r}),C.on(r?"keydown":"keyup",N),C.off(r?"keyup":"keydown",N)))},S&&C.on("init",function(e){N(e,!0),C.on("change SetContent ExecCommand",N),C.on("paste",function(e){return Ar.setEditorTimeout(C,function(){return N(e)})})});var A=vh(t);(function(t){var e=t.settings,n=t.getDoc(),r=t.getBody();t.fire("PreInit"),e.browser_spellcheck||e.gecko_spellcheck||(n.body.spellcheck=!1,Q1.setAttrib(r,"spellcheck","false")),t.quirks=k1(t),t.fire("PostRender");var o=t.getParam("directionality",lu.isRtl()?"rtl":void 0);void 0!==o&&(r.dir=o),e.protect&&t.on("BeforeSetContent",function(t){Nt.each(e.protect,function(e){t.content=t.content.replace(e,function(e){return"\x3c!--mce:protected "+escape(e)+"--\x3e"})})}),t.on("SetContent",function(){t.addVisual(t.getBody())}),t.on("compositionstart compositionend",function(e){t.composing="compositionstart"===e.type})})(t),A.fold(function(){O1(t).then(function(){return B1(t)})},function(e){t.setProgressState(!0),O1(t).then(function(){e().then(function(e){t.setProgressState(!1),B1(t)},function(e){t.notificationManager.open({type:"error",text:String(e)}),B1(t)})})})}function L1(e,t){var n,r,o,i,a=e.translate("Rich Text Area"),u=(n=e.id,r=a,t.height,o=e.getParam("iframe_attrs",{}),hn(i=Et.fromTag("iframe"),o),hn(i,{id:n+"_ifr",frameBorder:"0",allowTransparency:"true",title:r}),vu(i,"tox-edit-area__iframe"),i.dom);u.onload=function(){u.onload=null,e.fire("load")};var s=function(e,t){if(document.domain!==window.location.hostname&&xt.browser.isIE()){var n=ob("mce");e[n]=function(){P1(e)};var r='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinymce.get("'+e.id+'");document.write(ed.iframeHTML);document.close();ed.'+n+"(true);})()";return Z1.setAttrib(t,"src",r),!0}return!1}(e,u);return e.contentAreaContainer=t.iframeContainer,e.iframeElement=u,e.iframeHTML=function(e){var t=e.getParam("doctype","<!DOCTYPE html>")+"<html><head>";e.getParam("document_base_url","")!==e.documentBaseUrl&&(t+='<base href="'+e.documentBaseURI.getURI()+'" />'),t+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';var n=Ns(e,"body_id","tinymce"),r=Ns(e,"body_class",""),o=e.translate(e.getParam("iframe_aria_text","Rich Text Area. Press ALT-0 for help.","string"));return Es(e)&&(t+='<meta http-equiv="Content-Security-Policy" content="'+Es(e)+'" />'),t+('</head><body id="'+n+'" class="mce-content-body '+r+'" data-id="'+e.id)+'" aria-label="'+o+'"><br></body></html>'}(e),Z1.add(t.iframeContainer,u),s}function I1(e){return e.replace(/^\-/,"")}function M1(e){return{editorContainer:e,iframeContainer:e,api:{}}}function F1(e){var t,n,r,o,i,a,u,s=e.getElement();return e.orgDisplay=s.style.display,X(Is(e))?e.theme.renderUI():y(Is(e))?(n=(t=e).getElement(),(r=Is(t)(t,n)).editorContainer.nodeType&&(r.editorContainer.id=r.editorContainer.id||t.id+"_parent"),r.iframeContainer&&r.iframeContainer.nodeType&&(r.iframeContainer.id=r.iframeContainer.id||t.id+"_iframecontainer"),r.height=r.iframeHeight||n.offsetHeight,r):(u=(o=e).getElement(),o.inline?M1(null):(i=u,a=ex.create("div"),ex.insertAfter(a,i),M1(a)))}function U1(e){var n,t,r,o,i,a,u,s;e.fire("ScriptsLoaded"),n=e,t=Nt.trim(Rs(n)),r=n.ui.registry.getAll().icons,ne(_e(_e({},Vv.get("default").icons),Vv.get(t).icons),function(e,t){Ee(r,t)||n.ui.registry.addIcon(t,e)}),a=Is(o=e),X(a)?(o.settings.theme=I1(a),i=Yv.get(a),o.theme=new i(o,Yv.urls[a]),o.theme.init&&o.theme.init(o,Yv.urls[a]||o.documentBaseUrl.replace(/\/$/,""),o.$)):o.theme={},s=[],Nt.each(Fs(u=e).split(/[ ,]/),function(e){tx(u,s,I1(e))});var c=F1(e),l=e,f=ve.from(c.api).getOr({}),d={show:ve.from(f.show).getOr(te),hide:ve.from(f.hide).getOr(te),disable:ve.from(f.disable).getOr(te),isDisabled:ve.from(f.isDisabled).getOr(D),enable:function(){l.mode.isReadOnly()||ve.from(f.enable).map(x)}};l.ui=_e(_e({},l.ui),d);var m,g,p,h={editorContainer:c.editorContainer,iframeContainer:c.iframeContainer};return e.editorContainer=h.editorContainer||null,nb(e),e.inline?P1(e):(p=L1(m=e,g=h),g.editorContainer&&(Z1.get(g.editorContainer).style.display=m.orgDisplay,m.hidden=Z1.isHidden(g.editorContainer)),m.getElement().style.display="none",Z1.setAttrib(m.id,"aria-hidden","true"),void(p||P1(m)))}function z1(e){return"-"===e.charAt(0)}function H1(t,e,n){return ve.from(e).filter(function(e){return 0<e.length&&!Vv.has(e)}).map(function(e){return{url:t.editorManager.baseURL+"/icons/"+e+"/icons"+n+".js",name:ve.some(e)}})}function j1(c,l){var e,t,f=ou.ScriptLoader,n=f,r=l,o=function(){var r,o,t,n,e,i,a,u,s;e=f,u=Ts(i=c),s=i.getParam("language_url","","string"),!1===lu.hasCode(u)&&"en"!==u&&(a=""!==s?s:i.editorManager.baseURL+"/langs/"+u+".js",e.add(a,te,void 0,function(){Zv(i,"LanguageLoadError",eb("language",a,u))})),t=f,Y(function(e){for(var t=[],n=function(e){t.push(e)},r=0;r<e.length;r++)e[r].each(n);return t}([H1(n=c,"default",l),ve.from(n.getParam("icons_url","","string")).filter(function(e){return 0<e.length}).map(function(e){return{url:e,name:ve.none()}}).orThunk(function(){return H1(n,Rs(n),"")})]),function(e){t.add(e.url,te,void 0,function(){Zv(n,"IconsLoadError",eb("icons",e.url,e.name.getOrUndefined()))})}),r=c,o=l,Nt.each(r.getParam("external_plugins"),function(e,t){Xv.load(t,e,te,void 0,function(){tb(r,e,t)}),r.settings.plugins+=" "+t}),Nt.each(Fs(r).split(/[ ,]/),function(e){var t,n;(e=Nt.trim(e))&&!Xv.urls[e]&&(z1(e)?(e=e.substr(1,e.length),t=Xv.dependencies(e),Nt.each(t,function(e){var t=Xv.createUrl({prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"},e);Xv.load(t.resource,t,te,void 0,function(){tb(r,t.prefix+t.resource+t.suffix,t.resource)})})):(n={prefix:"plugins/",resource:e,suffix:"/plugin"+o+".js"},Xv.load(e,n,te,void 0,function(){tb(r,n.prefix+n.resource+n.suffix,e)})))}),f.loadQueue(function(){c.removed||U1(c)},c,function(){c.removed||U1(c)})},i=Is(e=c);X(i)?(z1(i)||Ee(Yv.urls,i)||((t=e.getParam("theme_url"))?Yv.load(i,e.documentBaseURI.toAbsolute(t)):Yv.load(i,"themes/"+i+"/theme"+r+".js")),n.loadQueue(function(){Yv.waitFor(i,o)})):o()}function V1(a){return function(i,e){return ve.from(e).map(Et.fromDom).filter(_n).bind(function(e){return n=a,t=i,r=e.dom,Tg(Et.fromDom(r),function(e){return Sn(t=e,n).orThunk(function(){return"font"===kt(t)?ue(rx,n).bind(function(e){return bn(t,e)}):ve.none()});var t},function(e){return je(Et.fromDom(t),e)}).or((o=e.dom,ve.from(eu.DOM.getStyle(o,a,!0))));var n,t,r,o}).getOr("")}}function q1(e){return rf(e.getBody()).map(function(e){var t=e.container();return Vn(t)?t.parentNode:t})}function $1(e,t){return n=e,r=a(ve.some,t),o=n,ve.from(o.selection.getRng()).bind(function(e){var t=o.getBody();return e.startContainer===t&&0===e.startOffset?ve.none():ve.from(o.selection.getStart(!0))}).orThunk(R(q1,n)).map(Et.fromDom).filter(_n).bind(r);var n,r,o}function W1(e,t){if(/^[0-9.]+$/.test(t)){var n=parseInt(t,10);if(1<=n&&n<=7){var r=Nt.explode(e.getParam("font_size_style_values","xx-small,x-small,small,medium,large,x-large,xx-large")),o=Nt.explode(e.getParam("font_size_classes",""));return o?o[n-1]||t:r[n-1]||t}return t}return t}var K1=Gn,X1=Yn,Y1=function(e){e.on(function(e){C1(e.ghost)}),e.clear()},G1=Yn,J1=Gn,Q1=eu.DOM,Z1=eu.DOM,ex=eu.DOM,tx=function(t,n,r){var o,i,a,u,e=Xv.get(r),s=Xv.urls[r]||t.documentBaseUrl.replace(/\/$/,"");if(r=Nt.trim(r),e&&-1===Nt.inArray(n,r)&&(Nt.each(Xv.dependencies(r),function(e){tx(t,n,e)}),!t.plugins[r]))try{var c=new e(t,s,t.$);(t.plugins[r]=c).init&&(c.init(t,s),n.push(r))}catch(e){i=r,a=e,Cf(o=t,"PluginLoadError",{message:u=lu.translate(["Failed to initialize plugin: {0}",i])}),wy(u,a),Qv(o,u)}},nx=eu.DOM,rx={"font-size":"size","font-family":"face"},ox=V1("font-size"),ix=i(function(e){return e.replace(/[\'\"\\]/g,"").replace(/,\s+/g,",")},V1("font-family")),ax=Nt.each,ux=Nt.map,sx=Nt.inArray,cx=(lx.prototype.execCommand=function(t,n,r,e){var o,i,a=!1,u=this;if(!u.editor.removed){if("mcefocus"!==t.toLowerCase()&&(/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(t)||e&&e.skip_focus?md(i=u.editor).each(function(e){return i.selection.setRng(e)}):u.editor.focus()),(e=u.editor.fire("BeforeExecCommand",{command:t,ui:n,value:r})).isDefaultPrevented())return!1;var s=t.toLowerCase();if(o=u.commands.exec[s])return o(s,n,r),u.editor.fire("ExecCommand",{command:t,ui:n,value:r}),!0;if(ax(this.editor.plugins,function(e){if(e.execCommand&&e.execCommand(t,n,r))return u.editor.fire("ExecCommand",{command:t,ui:n,value:r}),!(a=!0)}),a)return a;if(u.editor.theme&&u.editor.theme.execCommand&&u.editor.theme.execCommand(t,n,r))return u.editor.fire("ExecCommand",{command:t,ui:n,value:r}),!0;try{a=u.editor.getDoc().execCommand(t,n,r)}catch(e){}return!!a&&(u.editor.fire("ExecCommand",{command:t,ui:n,value:r}),!0)}},lx.prototype.queryCommandState=function(e){var t;if(!this.editor.quirks.isHidden()&&!this.editor.removed){if(e=e.toLowerCase(),t=this.commands.state[e])return t(e);try{return this.editor.getDoc().queryCommandState(e)}catch(e){}return!1}},lx.prototype.queryCommandValue=function(e){var t;if(!this.editor.quirks.isHidden()&&!this.editor.removed){if(e=e.toLowerCase(),t=this.commands.value[e])return t(e);try{return this.editor.getDoc().queryCommandValue(e)}catch(e){}}},lx.prototype.addCommands=function(e,n){void 0===n&&(n="exec");var r=this;ax(e,function(t,e){ax(e.toLowerCase().split(","),function(e){r.commands[n][e]=t})})},lx.prototype.addCommand=function(e,o,i){var a=this;e=e.toLowerCase(),this.commands.exec[e]=function(e,t,n,r){return o.call(i||a.editor,t,n,r)}},lx.prototype.queryCommandSupported=function(e){if(e=e.toLowerCase(),this.commands.exec[e])return!0;try{return this.editor.getDoc().queryCommandSupported(e)}catch(e){}return!1},lx.prototype.addQueryStateHandler=function(e,t,n){var r=this;e=e.toLowerCase(),this.commands.state[e]=function(){return t.call(n||r.editor)}},lx.prototype.addQueryValueHandler=function(e,t,n){var r=this;e=e.toLowerCase(),this.commands.value[e]=function(){return t.call(n||r.editor)}},lx.prototype.hasCustomCommand=function(e){return e=e.toLowerCase(),!!this.commands.exec[e]},lx.prototype.execNativeCommand=function(e,t,n){return void 0===t&&(t=!1),void 0===n&&(n=null),this.editor.getDoc().execCommand(e,t,n)},lx.prototype.isFormatMatch=function(e){return this.editor.formatter.match(e)},lx.prototype.toggleFormat=function(e,t){this.editor.formatter.toggle(e,t),this.editor.nodeChanged()},lx.prototype.storeSelection=function(e){this.selectionBookmark=this.editor.selection.getBookmark(e)},lx.prototype.restoreSelection=function(){this.editor.selection.moveToBookmark(this.selectionBookmark)},lx.prototype.setupCommands=function(u){var o=this;function e(r){return function(){var e=u.selection,t=e.isCollapsed()?[u.dom.getParent(e.getNode(),u.dom.isBlock)]:e.getSelectedBlocks(),n=ux(t,function(e){return!!u.formatter.matchNode(e,r)});return-1!==sx(n,!0)}}this.addCommands({"mceResetDesignMode,mceBeginUndoLevel":te,"mceEndUndoLevel,mceAddUndoLevel":function(){u.undoManager.add()},mceFocus:function(e,t,n){var r,o;o=n,(r=u).removed||(o?zd:function(t){var e=t.selection,n=t.getBody(),r=e.getRng();t.quirks.refreshContentEditable(),void 0!==t.bookmark&&!1===Cd(t)&&md(t).each(function(e){t.selection.setRng(e),r=e});var o,i,a=(o=t,i=e.getNode(),o.dom.getParent(i,function(e){return"true"===o.dom.getContentEditable(e)}));if(t.$.contains(n,a))return yd(a),bd(t,r),zd(t);t.inline||(xt.opera||yd(n),t.getWin().focus()),(xt.gecko||t.inline)&&(yd(n),bd(t,r)),zd(t)})(r)},"Cut,Copy,Paste":function(e){var t,n,r=u.getDoc();try{o.execNativeCommand(e)}catch(e){t=!0}!(t="paste"===e&&!r.queryCommandEnabled(e)||t)&&r.queryCommandSupported(e)||(n=u.translate("Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead."),xt.mac&&(n=n.replace(/Ctrl\+/g,"\u2318+")),u.notificationManager.open({text:n,type:"error"}))},unlink:function(){var e;u.selection.isCollapsed()?(e=u.dom.getParent(u.selection.getStart(),"a"))&&u.dom.remove(e,!0):u.formatter.remove("link")},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull,JustifyNone":function(e){var t=e.substring(7);"full"===t&&(t="justify"),ax("left,center,right,justify".split(","),function(e){t!==e&&u.formatter.remove("align"+e)}),"none"!==t&&o.toggleFormat("align"+t)},"InsertUnorderedList,InsertOrderedList":function(e){var t;o.execNativeCommand(e);var n=u.dom.getParent(u.selection.getNode(),"ol,ul");n&&(t=n.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(t.nodeName)&&(o.storeSelection(),u.dom.split(t,n),o.restoreSelection()))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){o.toggleFormat(e)},"ForeColor,HiliteColor":function(e,t,n){o.toggleFormat(e,{value:n})},FontName:function(e,t,n){var r,o;o=W1(r=u,n),r.formatter.toggle("fontname",{value:A(o.split(/\s*,\s*/),function(e){return-1===e.indexOf(" ")||Ge(e,'"')||Ge(e,"'")?e:"'"+e+"'"}).join(",")}),r.nodeChanged()},FontSize:function(e,t,n){var r;(r=u).formatter.toggle("fontsize",{value:W1(r,n)}),r.nodeChanged()},LineHeight:function(e,t,n){var r;(r=u).formatter.toggle("lineheight",{value:String(n)}),r.nodeChanged()},Lang:function(e,t,n){o.toggleFormat(e,{value:n.code,customValue:n.customCode})},RemoveFormat:function(e){u.formatter.remove(e)},mceBlockQuote:function(){o.toggleFormat("blockquote")},FormatBlock:function(e,t,n){return o.toggleFormat(n||"p")},mceCleanup:function(){var e=u.selection.getBookmark();u.setContent(u.getContent()),u.selection.moveToBookmark(e)},mceRemoveNode:function(e,t,n){var r=n||u.selection.getNode();r!==u.getBody()&&(o.storeSelection(),u.dom.remove(r,!0),o.restoreSelection())},mceSelectNodeDepth:function(e,t,n){var r=0;u.dom.getParent(u.selection.getNode(),function(e){if(1===e.nodeType&&r++===n)return u.selection.select(e),!1},u.getBody())},mceSelectNode:function(e,t,n){u.selection.select(n)},mceInsertContent:function(e,t,n){var r,o,i,a;r=u,o=function(e){if("string"==typeof e)return{content:e,details:{}};var t=Nt.extend({paste:e.paste,data:{paste:e.paste}},e);return{content:e.content,details:t}}(n),i=o.content,a=o.details,bh(r).editor.insertContent(i,a)},mceInsertRawHTML:function(e,t,n){u.selection.setContent("tiny_mce_marker");var r=u.getContent();u.setContent(r.replace(/tiny_mce_marker/g,function(){return n}))},mceInsertNewLine:function(e,t,n){VC(u,n)},mceToggleFormat:function(e,t,n){o.toggleFormat(n)},mceSetContent:function(e,t,n){u.setContent(n)},"Indent,Outdent":function(e){I0(u,e)},mceRepaint:te,InsertHorizontalRule:function(){u.execCommand("mceInsertContent",!1,"<hr />")},mceToggleVisualAid:function(){u.hasVisual=!u.hasVisual,u.addVisual()},mceReplaceContent:function(e,t,n){u.execCommand("mceInsertContent",!1,n.replace(/\{\$selection\}/g,u.selection.getContent({format:"text"})))},mceInsertLink:function(e,t,n){"string"==typeof n&&(n={href:n});var r=u.dom.getParent(u.selection.getNode(),"a");n.href=n.href.replace(/ /g,"%20"),r&&n.href||u.formatter.remove("link"),n.href&&u.formatter.apply("link",n,r)},selectAll:function(){var e,t=u.dom.getParent(u.selection.getStart(),Yn);t&&((e=u.dom.createRng()).selectNodeContents(t),u.selection.setRng(e))},mceNewDocument:function(){u.setContent("")},InsertLineBreak:function(e,t,n){return TC(u,n),!0}}),o.addCommands({JustifyLeft:e("alignleft"),JustifyCenter:e("aligncenter"),JustifyRight:e("alignright"),JustifyFull:e("alignjustify"),"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(e){return o.isFormatMatch(e)},mceBlockQuote:function(){return o.isFormatMatch("blockquote")},Outdent:function(){return P0(u)},"InsertUnorderedList,InsertOrderedList":function(e){var t=u.dom.getParent(u.selection.getNode(),"ul,ol");return t&&("insertunorderedlist"===e&&"UL"===t.tagName||"insertorderedlist"===e&&"OL"===t.tagName)}},"state"),o.addCommands({Undo:function(){u.undoManager.undo()},Redo:function(){u.undoManager.redo()}}),o.addQueryValueHandler("FontName",function(){return $1(t=u,function(e){return ix(t.getBody(),e.dom)}).getOr("");var t},this),o.addQueryValueHandler("FontSize",function(){return $1(t=u,function(e){return ox(t.getBody(),e.dom)}).getOr("");var t},this),o.addQueryValueHandler("LineHeight",function(){return $1(t=u,function(n){var e=Et.fromDom(t.getBody());return Tg(n,function(e){return Sn(e,"line-height")},R(je,e)).getOrThunk(function(){var e=parseFloat(wn(n,"line-height")),t=parseFloat(wn(n,"font-size"));return String(e/t)})}).getOr("");var t},this)},lx);function lx(e){this.commands={state:{},exec:{},value:{}},this.editor=e,this.setupCommands(e)}function fx(e,t,n){var r,o,i,a,u,s;bu(e,t)&&!1===n?(o=t,hu(r=e)?r.dom.classList.remove(o):(u=o,0<(s=U(pu(a=r,"class"),function(e){return e!==u})).length?pn(a,"class",s.join(" ")):Cn(a,"class")),0===(hu(i=r)?i.dom.classList:pu(i,"class")).length&&Cn(i,"class")):n&&vu(e,t)}function dx(e,t,n){try{e.getDoc().execCommand(t,!1,String(n))}catch(e){}}function mx(e,t){e.dom.contentEditable=t?"true":"false"}function gx(e,t){var n,r,o=Et.fromDom(e.getBody());fx(o,"mce-content-readonly",t),t?(e.selection.controlSelection.hideResizeRect(),e._selectionOverrides.hideFakeCaret(),ve.from(e.selection.getNode()).each(function(e){e.removeAttribute("data-mce-selected")}),mx(o,!(e.readonly=!0)),Y(yu(o,'*[contenteditable="true"]'),function(e){pn(e,vx,"true"),mx(e,!1)})):(mx(o,!(e.readonly=!1)),Y(yu(o,"*["+vx+'="true"]'),function(e){Cn(e,vx),mx(e,!0)}),dx(e,"StyleWithCSS",!1),dx(e,"enableInlineTableEditing",!1),dx(e,"enableObjectResizing",!1),(Cd(n=e)||(r=n,od(Pn(Et.fromDom(r.getElement()))).filter(function(e){return!(void 0!==(t=e.dom.classList)&&(t.contains("tox-edit-area")||t.contains("tox-edit-area__iframe")||t.contains("mce-content-body")))&&pd(r,e.dom);var t}).isSome()))&&e.focus(),e.selection.setRng(e.selection.getRng()),e.nodeChanged())}function px(e){return e.readonly}function hx(t){t.parser.addAttributeFilter("contenteditable",function(e){px(t)&&Y(e,function(e){e.attr(vx,e.attr("contenteditable")),e.attr("contenteditable","false")})}),t.serializer.addAttributeFilter(vx,function(e){px(t)&&Y(e,function(e){e.attr("contenteditable",e.attr(vx))})}),t.serializer.addTempAttr(vx)}var vx="data-mce-contenteditable",bx=Nt.makeMap("focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave wheel keydown keypress keyup input beforeinput contextmenu dragstart dragend dragover draggesture dragdrop drop drag submit compositionstart compositionend compositionupdate touchstart touchmove touchend touchcancel"," "),yx=(Cx.isNative=function(e){return!!bx[e.toLowerCase()]},Cx.prototype.fire=function(e,t){var n=e.toLowerCase(),r=so(n,t||{},this.scope);this.settings.beforeFire&&this.settings.beforeFire(r);var o=this.bindings[n];if(o)for(var i=0,a=o.length;i<a;i++){var u=o[i];if(!u.removed){if(u.once&&this.off(n,u.func),r.isImmediatePropagationStopped())return r;if(!1===u.func.call(this.scope,r))return r.preventDefault(),r}}return r},Cx.prototype.on=function(e,t,n,r){if(t=!1===t?D:t){var o={func:t,removed:!1};r&&Nt.extend(o,r);for(var i=e.toLowerCase().split(" "),a=i.length;a--;){var u=i[a],s=this.bindings[u];s||(s=[],this.toggleEvent(u,!0)),s=n?Ae([o],s,!0):Ae(Ae([],s,!0),[o],!1),this.bindings[u]=s}}return this},Cx.prototype.off=function(e,t){var n=this;if(e)for(var r=e.toLowerCase().split(" "),o=r.length;o--;){var i,a=r[o],u=this.bindings[a];if(!a)return ne(this.bindings,function(e,t){n.toggleEvent(t,!1),delete n.bindings[t]}),this;u&&(t?(u=(i=B(u,function(e){return e.func===t})).fail,this.bindings[a]=u,Y(i.pass,function(e){e.removed=!0})):u.length=0,u.length||(this.toggleEvent(e,!1),delete this.bindings[a]))}else ne(this.bindings,function(e,t){n.toggleEvent(t,!1)}),this.bindings={};return this},Cx.prototype.once=function(e,t,n){return this.on(e,t,n,{once:!0})},Cx.prototype.has=function(e){return e=e.toLowerCase(),!(!this.bindings[e]||0===this.bindings[e].length)},Cx);function Cx(e){this.bindings={},this.settings=e||{},this.scope=this.settings.scope||this,this.toggleEvent=this.settings.toggleEvent||D}function xx(n){return n._eventDispatcher||(n._eventDispatcher=new yx({scope:n,toggleEvent:function(e,t){yx.isNative(e)&&n.toggleNativeEvent&&n.toggleNativeEvent(e,t)}})),n._eventDispatcher}function wx(e,t){if("selectionchange"===t)return e.getDoc();if(!e.inline&&/^mouse|touch|click|contextmenu|drop|dragover|dragend/.test(t))return e.getDoc().documentElement;var n=Ls(e);return n?(e.eventRoot||(e.eventRoot=Rx.select(n)[0]),e.eventRoot):e.getBody()}function Sx(e,t,n){var r,o,i,a;e.hidden||px(e)?px(e)&&(r=e,"click"!==(o=n).type||If.metaKeyPressed(o)||(i=Et.fromDom(o.target),a=r,yr(i,"a",function(e){return je(e,Et.fromDom(a.getBody()))}).bind(function(e){return bn(e,"href")}).each(function(e){var t,n;o.preventDefault(),/^#/.test(e)?(t=r.dom.select(e+',[name="'+(Ge(n=e,"#")?n.substring("#".length):n)+'"]')).length&&r.selection.scrollIntoView(t[0],!0):window.open(e,"_blank","rel=noopener noreferrer,menubar=yes,toolbar=yes,location=yes,status=yes,resizable=yes,scrollbars=yes")}))):e.fire(t,n)}function Nx(i,a){var e,t;i.delegates||(i.delegates={}),i.delegates[a]||i.removed||(t=wx(i,a),Ls(i)?(_x||(_x={},i.editorManager.on("removeEditor",function(){i.editorManager.activeEditor||_x&&(ne(_x,function(e,t){i.dom.unbind(wx(i,t))}),_x=null)})),_x[a]||(_x[a]=e=function(e){for(var t=e.target,n=i.editorManager.get(),r=n.length;r--;){var o=n[r].getBody();o!==t&&!Rx.isChildOf(t,o)||Sx(n[r],a,e)}},Rx.bind(t,a,e))):(Rx.bind(t,a,e=function(e){Sx(i,a,e)}),i.delegates[a]=e))}function Ex(e,t,n,r){var o=n[t.get()],i=n[r];try{i.activate()}catch(e){return void console.error("problem while activating editor mode "+r+":",e)}o.deactivate(),o.editorReadOnly!==i.editorReadOnly&&gx(e,i.editorReadOnly),t.set(r),e.fire("SwitchMode",{mode:r})}function kx(e){var t,n={};Ox(Bx(e.toLowerCase(),"+"),function(e){e in Lx?n[e]=!0:/^[0-9]{2,}$/.test(e)?n.keyCode=parseInt(e,10):(n.charCode=e.charCodeAt(0),n.keyCode=Px[e]||e.toUpperCase().charCodeAt(0))});var r=[n.keyCode];for(t in Lx)n[t]?r.push(t):n[t]=!1;return n.id=r.join(","),n.access&&(n.alt=!0,xt.mac?n.ctrl=!0:n.shift=!0),n.meta&&(xt.mac?n.meta=!0:(n.ctrl=!0,n.meta=!1)),n}var _x,Ax={fire:function(e,t,n){if(this.removed&&"remove"!==e&&"detach"!==e)return t;var r=xx(this).fire(e,t);if(!1!==n&&this.parent)for(var o=this.parent();o&&!r.isPropagationStopped();)o.fire(e,r,!1),o=o.parent();return r},on:function(e,t,n){return xx(this).on(e,t,n)},off:function(e,t){return xx(this).off(e,t)},once:function(e,t){return xx(this).once(e,t)},hasEventListeners:function(e){return xx(this).has(e)}},Rx=eu.DOM,Dx=_e(_e({},Ax),{bindPendingEventDelegates:function(){var t=this;Nt.each(t._pendingNativeEvents,function(e){Nx(t,e)})},toggleNativeEvent:function(e,t){var n=this;"focus"!==e&&"blur"!==e&&(n.removed||(t?n.initialized?Nx(n,e):n._pendingNativeEvents?n._pendingNativeEvents.push(e):n._pendingNativeEvents=[e]:n.initialized&&(n.dom.unbind(wx(n,e),e,n.delegates[e]),delete n.delegates[e])))},unbindAllNativeEvents:function(){var n=this,e=n.getBody(),t=n.dom;n.delegates&&(ne(n.delegates,function(e,t){n.dom.unbind(wx(n,t),t,e)}),delete n.delegates),!n.inline&&e&&t&&(e.onload=null,t.unbind(n.getWin()),t.unbind(n.getDoc())),t&&(t.unbind(e),t.unbind(n.getContainer()))}}),Tx=["design","readonly"],Ox=Nt.each,Bx=Nt.explode,Px={f1:112,f2:113,f3:114,f4:115,f5:116,f6:117,f7:118,f8:119,f9:120,f10:121,f11:122,f12:123},Lx=Nt.makeMap("alt,ctrl,shift,meta,access"),Ix=(Mx.prototype.add=function(e,n,t,r){var o=this,i=o.normalizeCommandFunc(t);return Ox(Bx(Nt.trim(e)),function(e){var t=o.createShortcut(e,n,i,r);o.shortcuts[t.id]=t}),!0},Mx.prototype.remove=function(e){var t=this.createShortcut(e);return!!this.shortcuts[t.id]&&(delete this.shortcuts[t.id],!0)},Mx.prototype.normalizeCommandFunc=function(e){var t=this,n=e;return"string"==typeof n?function(){t.editor.execCommand(n,!1,null)}:Nt.isArray(n)?function(){t.editor.execCommand(n[0],n[1],n[2])}:n},Mx.prototype.createShortcut=function(e,t,n,r){var o=Nt.map(Bx(e,">"),kx);return o[o.length-1]=Nt.extend(o[o.length-1],{func:n,scope:r||this.editor}),Nt.extend(o[0],{desc:this.editor.translate(t),subpatterns:o.slice(1)})},Mx.prototype.hasModifier=function(e){return e.altKey||e.ctrlKey||e.metaKey},Mx.prototype.isFunctionKey=function(e){return"keydown"===e.type&&112<=e.keyCode&&e.keyCode<=123},Mx.prototype.matchShortcut=function(e,t){return!!t&&t.ctrl===e.ctrlKey&&t.meta===e.metaKey&&t.alt===e.altKey&&t.shift===e.shiftKey&&!!(e.keyCode===t.keyCode||e.charCode&&e.charCode===t.charCode)&&(e.preventDefault(),!0)},Mx.prototype.executeShortcutAction=function(e){return e.func?e.func.call(e.scope):null},Mx);function Mx(e){this.shortcuts={},this.pendingPatterns=[],this.editor=e;var n=this;e.on("keyup keypress keydown",function(t){!n.hasModifier(t)&&!n.isFunctionKey(t)||t.isDefaultPrevented()||(Ox(n.shortcuts,function(e){if(n.matchShortcut(t,e))return n.pendingPatterns=e.subpatterns.slice(0),"keydown"===t.type&&n.executeShortcutAction(e),!0}),n.matchShortcut(t,n.pendingPatterns[0])&&(1===n.pendingPatterns.length&&"keydown"===t.type&&n.executeShortcutAction(n.pendingPatterns[0]),n.pendingPatterns.shift()))})}var Fx=eu.DOM,Ux=Nt.extend,zx=Nt.each,Hx=Nt.resolve,jx=xt.ie,Vx=(qx.prototype.render=function(){!function(t){var e=t.id;lu.setCode(Ts(t));var n,r,o,i,a=function(){nx.unbind(window,"ready",a),t.render()};ci.Event.domLoaded?t.getElement()&&xt.contentEditable&&(n=Et.fromDom(t.getElement()),r=L(n.dom.attributes,function(e,t){return e[t.name]=t.value,e},{}),t.on("remove",function(){O(n.dom.attributes,function(e){return Cn(n,e.name),0}),hn(n,r)}),t.ui.styleSheetLoader=Rr.forElement(n,{contentCssCors:(o=t).getParam("content_css_cors"),referrerPolicy:Ds(o)}),t.getParam("inline")?t.inline=!0:(t.orgVisibility=t.getElement().style.visibility,t.getElement().style.visibility="hidden"),(i=t.getElement().form||nx.getParent(e,"form"))&&(t.formElement=i,t.getParam("hidden_input")&&!jn(t.getElement())&&(nx.insertAfter(nx.create("input",{type:"hidden",name:e}),e),t.hasHiddenInput=!0),t.formEventDelegate=function(e){t.fire(e.type,e)},nx.bind(i,"submit reset",t.formEventDelegate),t.on("reset",function(){t.resetContent()}),!t.getParam("submit_patch")||i.submit.nodeType||i.submit.length||i._mceOldSubmit||(i._mceOldSubmit=i.submit,i.submit=function(){return t.editorManager.triggerSave(),t.setDirty(!1),i._mceOldSubmit(i)})),t.windowManager=Gv(t),t.notificationManager=Ev(t),"xml"===t.getParam("encoding")&&t.on("GetContent",function(e){e.save&&(e.content=nx.encode(e.content))}),t.getParam("add_form_submit_trigger")&&t.on("submit",function(){t.initialized&&t.save()}),t.getParam("add_unload_trigger")&&(t._beforeUnload=function(){!t.initialized||t.destroyed||t.isHidden()||t.save({format:"raw",no_events:!0,set_dirty:!1})},t.editorManager.on("BeforeUnload",t._beforeUnload)),t.editorManager.add(t),j1(t,t.suffix)):nx.bind(window,"ready",a)}(this)},qx.prototype.focus=function(e){this.execCommand("mceFocus",!1,e)},qx.prototype.hasFocus=function(){return Cd(this)},qx.prototype.execCallback=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r,o=this.settings[e];if(o)return this.callbackLookup&&(r=this.callbackLookup[e])&&(o=r.func,r=r.scope),"string"==typeof o&&(r=(r=o.replace(/\.\w+$/,""))?Hx(r):0,o=Hx(o),this.callbackLookup=this.callbackLookup||{},this.callbackLookup[e]={func:o,scope:r}),o.apply(r||this,t)},qx.prototype.translate=function(e){return lu.translate(e)},qx.prototype.getParam=function(e,t,n){return i=t,a=n,l=(o=e)in(r=this).settings?r.settings[o]:i,"hash"===a?(c={},"string"==typeof(s=l)?Y(0<s.indexOf("=")?s.split(/[;,](?![^=;,]*(?:[;,]|$))/):s.split(","),function(e){var t=e.split("=");1<t.length?c[Nt.trim(t[0])]=Nt.trim(t[1]):c[Nt.trim(t[0])]=Nt.trim(t[0])}):c=s,c):"string"===a?xv(X,r,o).getOr(i):"number"===a?xv(N,r,o).getOr(i):"boolean"===a?xv(v,r,o).getOr(i):"object"===a?xv(h,r,o).getOr(i):"array"===a?xv(S,r,o).getOr(i):"string[]"===a?xv((u=X,function(e){return S(e)&&j(e,u)}),r,o).getOr(i):"function"===a?xv(y,r,o).getOr(i):l;var r,o,i,a,u,s,c,l},qx.prototype.hasPlugin=function(e,t){return!(!T(Fs(this).split(/[ ,]/),e)||t&&void 0===Xv.get(e))},qx.prototype.nodeChanged=function(e){this._nodeChangeDispatcher.nodeChanged(e)},qx.prototype.addCommand=function(e,t,n){this.editorCommands.addCommand(e,t,n)},qx.prototype.addQueryStateHandler=function(e,t,n){this.editorCommands.addQueryStateHandler(e,t,n)},qx.prototype.addQueryValueHandler=function(e,t,n){this.editorCommands.addQueryValueHandler(e,t,n)},qx.prototype.addShortcut=function(e,t,n,r){this.shortcuts.add(e,t,n,r)},qx.prototype.execCommand=function(e,t,n,r){return this.editorCommands.execCommand(e,t,n,r)},qx.prototype.queryCommandState=function(e){return this.editorCommands.queryCommandState(e)},qx.prototype.queryCommandValue=function(e){return this.editorCommands.queryCommandValue(e)},qx.prototype.queryCommandSupported=function(e){return this.editorCommands.queryCommandSupported(e)},qx.prototype.show=function(){this.hidden&&(this.hidden=!1,this.inline?this.getBody().contentEditable="true":(Fx.show(this.getContainer()),Fx.hide(this.id)),this.load(),this.fire("show"))},qx.prototype.hide=function(){var e=this,t=e.getDoc();e.hidden||(jx&&t&&!e.inline&&t.execCommand("SelectAll"),e.save(),e.inline?(e.getBody().contentEditable="false",e===e.editorManager.focusedEditor&&(e.editorManager.focusedEditor=null)):(Fx.hide(e.getContainer()),Fx.setStyle(e.id,"display",e.orgDisplay)),e.hidden=!0,e.fire("hide"))},qx.prototype.isHidden=function(){return!!this.hidden},qx.prototype.setProgressState=function(e,t){this.fire("ProgressState",{state:e,time:t})},qx.prototype.load=function(e){var t=this.getElement();if(this.removed)return"";if(t){(e=e||{}).load=!0;var n=jn(t)?t.value:t.innerHTML,r=this.setContent(n,e);return e.element=t,e.no_events||this.fire("LoadContent",e),e.element=t=null,r}},qx.prototype.save=function(e){var t,n,r=this,o=r.getElement();if(o&&r.initialized&&!r.removed)return(e=e||{}).save=!0,e.element=o,e.content=r.getContent(e),e.no_events||r.fire("SaveContent",e),"raw"===e.format&&r.fire("RawSaveContent",e),t=e.content,jn(o)?o.value=t:(!e.is_removing&&r.inline||(o.innerHTML=t),(n=Fx.getParent(r.id,"form"))&&zx(n.elements,function(e){if(e.name===r.id)return e.value=t,!1})),e.element=o=null,!1!==e.set_dirty&&r.setDirty(!1),t},qx.prototype.setContent=function(e,t){return mv(this,e,t)},qx.prototype.getContent=function(e){return t=this,r=(n=void 0===(n=e)?{}:n).format||"html",o=n,bh(t).editor.getContent(o,r);var t,n,r,o},qx.prototype.insertContent=function(e,t){t&&(e=Ux({content:e},t)),this.execCommand("mceInsertContent",!1,e)},qx.prototype.resetContent=function(e){void 0===e?mv(this,this.startContent,{format:"raw"}):mv(this,e),this.undoManager.reset(),this.setDirty(!1),this.nodeChanged()},qx.prototype.isDirty=function(){return!this.isNotDirty},qx.prototype.setDirty=function(e){var t=!this.isNotDirty;this.isNotDirty=!e,e&&e!==t&&this.fire("dirty")},qx.prototype.getContainer=function(){return this.container||(this.container=Fx.get(this.editorContainer||this.id+"_parent")),this.container},qx.prototype.getContentAreaContainer=function(){return this.contentAreaContainer},qx.prototype.getElement=function(){return this.targetElm||(this.targetElm=Fx.get(this.id)),this.targetElm},qx.prototype.getWin=function(){var e;return this.contentWindow||(e=this.iframeElement)&&(this.contentWindow=e.contentWindow),this.contentWindow},qx.prototype.getDoc=function(){var e;return this.contentDocument||(e=this.getWin())&&(this.contentDocument=e.document),this.contentDocument},qx.prototype.getBody=function(){var e=this.getDoc();return this.bodyElement||(e?e.body:null)},qx.prototype.convertURL=function(e,t,n){var r=this.settings;return r.urlconverter_callback?this.execCallback("urlconverter_callback",e,n,!0,t):!r.convert_urls||n&&"LINK"===n.nodeName||0===e.indexOf("file:")||0===e.length?e:r.relative_urls?this.documentBaseURI.toRelative(e):this.documentBaseURI.toAbsolute(e,r.remove_script_host)},qx.prototype.addVisual=function(e){var t;t=e,yh(this).editor.addVisual(t)},qx.prototype.remove=function(){var e,t,n,r,o;(e=this).removed||(t=e._selectionOverrides,n=e.editorUpload,r=e.getBody(),o=e.getElement(),r&&e.save({is_removing:!0}),e.removed=!0,e.unbindAllNativeEvents(),e.hasHiddenInput&&o&&Ov.remove(o.nextSibling),e.fire("remove"),e.editorManager.remove(e),!e.inline&&r&&Ov.setStyle(e.id,"display",e.orgDisplay),e.fire("detach"),Ov.remove(e.getContainer()),gv(t),gv(n),e.destroy())},qx.prototype.destroy=function(e){var t,n,r,o,i,a,u;n=e,a=(t=this).selection,u=t.dom,t.destroyed||(n||t.removed?(n||(t.editorManager.off("beforeunload",t._beforeUnload),t.theme&&t.theme.destroy&&t.theme.destroy(),gv(a),gv(u)),(o=(r=t).formElement)&&(o._mceOldSubmit&&(o.submit=o._mceOldSubmit,o._mceOldSubmit=null),Ov.unbind(o,"submit reset",r.formEventDelegate)),(i=t).contentAreaContainer=i.formElement=i.container=i.editorContainer=null,i.bodyElement=i.contentDocument=i.contentWindow=null,i.iframeElement=i.targetElm=null,i.selection&&(i.selection=i.selection.win=i.selection.dom=i.selection.dom.doc=null),t.destroyed=!0):t.remove())},qx.prototype.uploadImages=function(e){return this.editorUpload.uploadImages(e)},qx.prototype._scanForImages=function(){return this.editorUpload.scanForImages()},qx.prototype.addButton=function(){throw new Error("editor.addButton has been removed in tinymce 5x, use editor.ui.registry.addButton or editor.ui.registry.addToggleButton or editor.ui.registry.addSplitButton instead")},qx.prototype.addSidebar=function(){throw new Error("editor.addSidebar has been removed in tinymce 5x, use editor.ui.registry.addSidebar instead")},qx.prototype.addMenuItem=function(){throw new Error("editor.addMenuItem has been removed in tinymce 5x, use editor.ui.registry.addMenuItem instead")},qx.prototype.addContextToolbar=function(){throw new Error("editor.addContextToolbar has been removed in tinymce 5x, use editor.ui.registry.addContextToolbar instead")},qx);function qx(e,t,n){var r,o,i,a,u,s,c,l,f,d,m,g,p,h,v,b,y,C,x=this;function w(n,r){return function(e,t){return n[e.toLowerCase()]=_e(_e({},t),{type:r})}}this.plugins={},this.contentCSS=[],this.contentStyles=[],this.loadedCSS={},this.isNotDirty=!1,this.editorManager=n,this.documentBaseUrl=n.documentBaseURL,Ux(this,Dx),this.settings=(d=(f=this).documentBaseUrl,m=n.defaultSettings,p=d,h=Fv,v=f,b={id:e,theme:"silver",toolbar_mode:bv(g=t,"floating"),plugins:"",document_base_url:p,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"<!DOCTYPE html>",visual:!0,font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",forced_root_block:"p",hidden_input:!0,inline_styles:!0,convert_fonts_to_spans:!0,indent:!0,indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",entity_encoding:"named",url_converter:v.convertURL,url_converter_scope:v},y=_e(_e({},b),h?jv:{}),!1!==(C=Cv(Uv||zv,Uv,y,m,g)).deprecation_warnings&&pv(g,C),C),this.settings.suffix&&(n.suffix=this.settings.suffix),this.suffix=n.suffix,this.settings.base_url&&n._setBaseUrl(this.settings.base_url),this.baseUri=n.baseURI,this.settings.referrer_policy&&(ou.ScriptLoader._setReferrerPolicy(this.settings.referrer_policy),eu.DOM.styleSheetLoader._setReferrerPolicy(this.settings.referrer_policy)),fu.languageLoad=this.settings.language_load,fu.baseURL=n.baseURL,this.id=e,this.setDirty(!1),this.documentBaseURI=new nv(this.settings.document_base_url,{base_uri:this.baseUri}),this.baseURI=this.baseUri,this.inline=!!this.settings.inline,this.shortcuts=new Ix(this),this.editorCommands=new cx(this),this.settings.cache_suffix&&(xt.cacheSuffix=this.settings.cache_suffix.replace(/^[\?\&]+/,"")),this.ui={registry:{addAutocompleter:(u={},(r={addButton:w(o={},"button"),addGroupToolbarButton:w(o,"grouptoolbarbutton"),addToggleButton:w(o,"togglebutton"),addMenuButton:w(o,"menubutton"),addSplitButton:w(o,"splitbutton"),addMenuItem:w(i={},"menuitem"),addNestedMenuItem:w(i,"nestedmenuitem"),addToggleMenuItem:w(i,"togglemenuitem"),addAutocompleter:w(a={},"autocompleter"),addContextMenu:w(s={},"contextmenu"),addContextToolbar:w(c={},"contexttoolbar"),addContextForm:w(c,"contextform"),addSidebar:w(l={},"sidebar"),addIcon:function(e,t){return u[e.toLowerCase()]=t},getAll:function(){return{buttons:o,menuItems:i,icons:u,popups:a,contextMenus:s,contextToolbars:c,sidebars:l}}}).addAutocompleter),addButton:r.addButton,addContextForm:r.addContextForm,addContextMenu:r.addContextMenu,addContextToolbar:r.addContextToolbar,addIcon:r.addIcon,addMenuButton:r.addMenuButton,addMenuItem:r.addMenuItem,addNestedMenuItem:r.addNestedMenuItem,addSidebar:r.addSidebar,addSplitButton:r.addSplitButton,addToggleButton:r.addToggleButton,addGroupToolbarButton:r.addGroupToolbarButton,addToggleMenuItem:r.addToggleMenuItem,getAll:r.getAll},styleSheetLoader:void 0,show:te,hide:te,enable:te,disable:te,isDisabled:D};var S,N,E,k,_,A=(k=au("design"),_=au({design:{activate:te,deactivate:te,editorReadOnly:!1},readonly:{activate:te,deactivate:te,editorReadOnly:!0}}),(N=S=this).serializer?hx(N):N.on("PreInit",function(){hx(N)}),(E=S).on("ShowCaret",function(e){px(E)&&e.preventDefault()}),E.on("ObjectSelected",function(e){px(E)&&e.preventDefault()}),{isReadOnly:function(){return px(S)},set:function(e){return function(e,t,n,r){if(r!==n.get()){if(!Ee(t,r))throw new Error("Editor mode '"+r+"' is invalid");e.initialized?Ex(e,n,t,r):e.on("init",function(){return Ex(e,n,t,r)})}}(S,_.get(),k,e)},get:function(){return k.get()},register:function(e,t){_.set(function(e,t,n){var r;if(T(Tx,t))throw new Error("Cannot override default mode "+t);return _e(_e({},e),((r={})[t]=_e(_e({},n),{deactivate:function(){try{n.deactivate()}catch(e){console.error("problem while deactivating editor mode "+t+":",e)}}}),r))}(_.get(),e,t))}});this.mode=A,this.setMode=A.set,n.fire("SetupEditor",{editor:this}),this.execCallback("setup",this),this.$=Ya.overrideDefaults(function(){return{context:x.inline?x.getBody():x.getDoc(),element:x.getBody()}})}function $x(t){var n=t.type;Jx(ow.get(),function(e){switch(n){case"scroll":e.fire("ScrollWindow",t);break;case"resize":e.fire("ResizeWindow",t)}})}function Wx(e){e!==ew&&(e?Ya(window).on("resize scroll",$x):Ya(window).off("resize scroll",$x),ew=e)}function Kx(t){var e=nw;delete tw[t.id];for(var n=0;n<tw.length;n++)if(tw[n]===t){tw.splice(n,1);break}return nw=U(nw,function(e){return t!==e}),ow.activeEditor===t&&(ow.activeEditor=0<nw.length?nw[0]:null),ow.focusedEditor===t&&(ow.focusedEditor=null),e.length!==nw.length}var Xx,Yx=eu.DOM,Gx=Nt.explode,Jx=Nt.each,Qx=Nt.extend,Zx=0,ew=!1,tw=[],nw=[],rw="CSS1Compat"!==document.compatMode,ow=_e(_e({},Ax),{baseURI:null,baseURL:null,defaultSettings:{},documentBaseURL:null,suffix:null,$:Ya,majorVersion:"5",minorVersion:"10.9",releaseDate:"2023-11-15",editors:tw,i18n:lu,activeEditor:null,focusedEditor:null,settings:{},setup:function(){var e,t="",n=nv.getDocumentBaseUrl(document.location);/^[^:]+:\/\/\/?[^\/]+\//.test(n)&&(n=n.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,""),/[\/\\]$/.test(n)||(n+="/"));var r=window.tinymce||window.tinyMCEPreInit;if(r)e=r.base||r.baseURL,t=r.suffix;else{for(var o,i=document.getElementsByTagName("script"),a=0;a<i.length;a++)if(""!==(o=i[a].src||"")){var u=o.substring(o.lastIndexOf("/"));if(/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(o)){-1!==u.indexOf(".min")&&(t=".min"),e=o.substring(0,o.lastIndexOf("/"));break}}!e&&document.currentScript&&(-1!==(o=document.currentScript.src).indexOf(".min")&&(t=".min"),e=o.substring(0,o.lastIndexOf("/")))}this.baseURL=new nv(n).toAbsolute(e),this.documentBaseURL=n,this.baseURI=new nv(this.baseURL),this.suffix=t,this.on("AddEditor",R(hd,this)),this.on("RemoveEditor",R(vd,this))},overrideDefaults:function(e){var t=e.base_url;t&&this._setBaseUrl(t);var n=e.suffix;e.suffix&&(this.suffix=n);var r=(this.defaultSettings=e).plugin_base_urls;void 0!==r&&ne(r,function(e,t){fu.PluginManager.urls[t]=e})},init:function(r){function u(e){var t=e.id;return t||(t=ue(e,"name").filter(function(e){return!Yx.get(e)}).getOrThunk(Yx.uniqueId),e.setAttribute("id",t)),t}function s(e,t){return t.constructor===RegExp?t.test(e.className):Yx.hasClass(e,t)}var n,c=this,l=Nt.makeMap("area base basefont br col frame hr img input isindex link meta param embed source wbr track colgroup option table tbody tfoot thead tr th td script noscript style textarea video audio iframe object menu"," "),f=function(e){n=e},t=function(){function n(e,t,n){var r=new Vx(e,t,c);a.push(r),r.on("init",function(){++i===o.length&&f(a)}),r.targetElm=r.targetElm||n,r.render()}var o,e,i=0,a=[];Yx.unbind(window,"ready",t),(e=r.onpageload)&&e.apply(c,[]),o=Ya.unique(function(t){var n=[];if(xt.browser.isIE()&&xt.browser.version.major<11)return wy("TinyMCE does not support the browser you are using. For a list of supported browsers please see: https://www.tinymce.com/docs/get-started/system-requirements/"),[];if(rw)return wy("Failed to initialize the editor as the document is not in standards mode. TinyMCE requires standards mode."),[];if(t.types)return Jx(t.types,function(e){n=n.concat(Yx.select(e.selector))}),n;if(t.selector)return Yx.select(t.selector);if(t.target)return[t.target];switch(t.mode){case"exact":var e=t.elements||"";0<e.length&&Jx(Gx(e),function(t){var e=Yx.get(t);e?n.push(e):Jx(document.forms,function(e){Jx(e.elements,function(e){e.name===t&&(t="mce_editor_"+Zx++,Yx.setAttrib(e,"id",t),n.push(e))})})});break;case"textareas":case"specific_textareas":Jx(Yx.select("textarea"),function(e){t.editor_deselector&&s(e,t.editor_deselector)||t.editor_selector&&!s(e,t.editor_selector)||n.push(e)})}return n}(r)),r.types?Jx(r.types,function(t){Nt.each(o,function(e){return!Yx.is(e,t.selector)||(n(u(e),Qx({},r,t),e),!1)})}):(Nt.each(o,function(e){var t;(t=c.get(e.id))&&t.initialized&&!(t.getContainer()||t.getBody()).parentNode&&(Kx(t),t.unbindAllNativeEvents(),t.destroy(!0),t.removed=!0)}),0===(o=Nt.grep(o,function(e){return!c.get(e.id)})).length?f([]):Jx(o,function(e){var t=e;r.inline&&t.tagName.toLowerCase()in l?wy("Could not initialize inline editor on invalid inline target element",e):n(u(e),r,e)}))};return c.settings=r,Yx.bind(window,"ready",t),new _r(function(t){n?t(n):f=function(e){t(e)}})},get:function(t){return 0===arguments.length?nw.slice(0):X(t)?M(nw,function(e){return e.id===t}).getOr(null):N(t)&&nw[t]||null},add:function(e){var n=this;return tw[e.id]===e||(null===n.get(e.id)&&("length"!==e.id&&(tw[e.id]=e),tw.push(e),nw.push(e)),Wx(!0),n.activeEditor=e,n.fire("AddEditor",{editor:e}),Xx||(Xx=function(e){var t=n.fire("BeforeUnload");if(t.returnValue)return e.preventDefault(),e.returnValue=t.returnValue,t.returnValue},window.addEventListener("beforeunload",Xx))),e},createEditor:function(e,t){return this.add(new Vx(e,t,this))},remove:function(e){var t,n,r=this;if(e){if(!X(e))return n=e,l(r.get(n.id))?null:(Kx(n)&&r.fire("RemoveEditor",{editor:n}),0===nw.length&&window.removeEventListener("beforeunload",Xx),n.remove(),Wx(0<nw.length),n);Jx(Yx.select(e),function(e){(n=r.get(e.id))&&r.remove(n)})}else for(t=nw.length-1;0<=t;t--)r.remove(nw[t])},execCommand:function(e,t,n){var r=this.get(n);switch(e){case"mceAddEditor":return this.get(n)||new Vx(n,this.settings,this).render(),!0;case"mceRemoveEditor":return r&&r.remove(),!0;case"mceToggleEditor":return r?r.isHidden()?r.show():r.hide():this.execCommand("mceAddEditor",!1,n),!0}return!!this.activeEditor&&this.activeEditor.execCommand(e,t,n)},triggerSave:function(){Jx(nw,function(e){e.save()})},addI18n:function(e,t){lu.add(e,t)},translate:function(e){return lu.translate(e)},setActive:function(e){var t=this.activeEditor;this.activeEditor!==e&&(t&&t.fire("deactivate",{relatedTarget:e}),e.fire("activate",{relatedTarget:t})),this.activeEditor=e},_setBaseUrl:function(e){this.baseURL=new nv(this.documentBaseURL).toAbsolute(e.replace(/\/+$/,"")),this.baseURI=new nv(this.baseURL)}});function iw(e,t,n){var r=t.x,o=t.y,i=e.w,a=e.h,u=t.w,s=t.h,c=(n||"").split("");return"b"===c[0]&&(o+=s),"r"===c[1]&&(r+=u),"c"===c[0]&&(o+=gw(s/2)),"c"===c[1]&&(r+=gw(u/2)),"b"===c[3]&&(o-=a),"r"===c[4]&&(r-=i),"c"===c[3]&&(o-=gw(a/2)),"c"===c[4]&&(r-=gw(i/2)),uw(r,o,i,a)}function aw(){}ow.setup();function uw(e,t,n,r){return{x:e,y:t,w:n,h:r}}var sw,cw,lw,fw,dw=Math.min,mw=Math.max,gw=Math.round,pw={inflate:function(e,t,n){return uw(e.x-t,e.y-n,e.w+2*t,e.h+2*n)},relativePosition:iw,findBestRelativePosition:function(e,t,n,r){for(var o,i=0;i<r.length;i++)if((o=iw(e,t,r[i])).x>=n.x&&o.x+o.w<=n.w+n.x&&o.y>=n.y&&o.y+o.h<=n.h+n.y)return r[i];return null},intersect:function(e,t){var n=mw(e.x,t.x),r=mw(e.y,t.y),o=dw(e.x+e.w,t.x+t.w),i=dw(e.y+e.h,t.y+t.h);return o-n<0||i-r<0?null:uw(n,r,o-n,i-r)},clamp:function(e,t,n){var r=e.x,o=e.y,i=e.x+e.w,a=e.y+e.h,u=t.x+t.w,s=t.y+t.h,c=mw(0,t.x-r),l=mw(0,t.y-o),f=mw(0,i-u),d=mw(0,a-s);return r+=c,o+=l,n&&(i+=c,a+=l,r-=f,o-=d),uw(r,o,(i-=f)-r,(a-=d)-o)},create:uw,fromClientRect:function(e){return uw(e.left,e.top,e.width,e.height)}},hw=(sw={},cw={},{load:function(r,o){var i='Script at URL "'+o+'" failed to load',a='Script at URL "'+o+"\" did not call `tinymce.Resource.add('"+r+"', data)` within 1 second";if(void 0!==sw[r])return sw[r];var e=new _r(function(e,t){var n=function(e,t,n){function r(n){return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];o||(o=!0,null!==i&&(clearTimeout(i),i=null),n.apply(null,e))}}void 0===n&&(n=1e3);var o=!1,i=null,a=r(e),u=r(t);return{start:function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];o||null!==i||(i=setTimeout(function(){return u.apply(null,e)},n))},resolve:a,reject:u}}(e,t);cw[r]=n.resolve,ou.ScriptLoader.loadScript(o,function(){return n.start(a)},function(){return n.reject(i)})});return sw[r]=e},add:function(e,t){void 0!==cw[e]&&(cw[e](t),delete cw[e]),sw[e]=_r.resolve(t)}}),vw=Nt.each,bw=Nt.extend;aw.extend=lw=function(n){function r(){var e,t,n;if(!fw&&(this.init&&this.init.apply(this,arguments),t=this.Mixins))for(e=t.length;e--;)(n=t[e]).init&&n.init.apply(this,arguments)}function t(){return this}var o=this.prototype;fw=!0;var i=new this;return fw=!1,n.Mixins&&(vw(n.Mixins,function(e){for(var t in e)"init"!==t&&(n[t]=e[t])}),o.Mixins&&(n.Mixins=o.Mixins.concat(n.Mixins))),n.Methods&&vw(n.Methods.split(","),function(e){n[e]=t}),n.Properties&&vw(n.Properties.split(","),function(e){var t="_"+e;n[e]=function(e){return void 0!==e?(this[t]=e,this):this[t]}}),n.Statics&&vw(n.Statics,function(e,t){r[t]=e}),n.Defaults&&o.Defaults&&(n.Defaults=bw({},o.Defaults,n.Defaults)),ne(n,function(e,t){var n,r;"function"==typeof e&&o[t]?i[t]=(n=t,r=e,function(){var e=this._super;this._super=o[n];var t=r.apply(this,arguments);return this._super=e,t}):i[t]=e}),r.prototype=i,(r.constructor=r).extend=lw,r};var yw,Cw,xw,ww=Math.min,Sw=Math.max,Nw=Math.round,Ew={serialize:function(e){var t=JSON.stringify(e);return X(t)?t.replace(/[\u0080-\uFFFF]/g,function(e){var t=e.charCodeAt(0).toString(16);return"\\u"+"0000".substring(t.length)+t}):t},parse:function(e){try{return JSON.parse(e)}catch(e){}}},kw={callbacks:{},count:0,send:function(t){var n=this,r=eu.DOM,o=(void 0!==t.count?t:n).count,i="tinymce_jsonp_"+o;n.callbacks[o]=function(e){r.remove(i),delete n.callbacks[o],t.callback(e)},r.add(r.doc.body,"script",{id:i,src:t.url,type:"text/javascript"}),n.count++}},_w=_e(_e({},Ax),{send:function(e){var t,n=0,r=function(){!e.async||4===t.readyState||1e4<n++?(e.success&&n<1e4&&200===t.status?e.success.call(e.success_scope,""+t.responseText,t,e):e.error&&e.error.call(e.error_scope,1e4<n?"TIMED_OUT":"GENERAL",t,e),t=null):Ar.setTimeout(r,10)};if(e.scope=e.scope||this,e.success_scope=e.success_scope||e.scope,e.error_scope=e.error_scope||e.scope,e.async=!1!==e.async,e.data=e.data||"",_w.fire("beforeInitialize",{settings:e}),(t=new XMLHttpRequest).overrideMimeType&&t.overrideMimeType(e.content_type),t.open(e.type||(e.data?"POST":"GET"),e.url,e.async),e.crossDomain&&(t.withCredentials=!0),e.content_type&&t.setRequestHeader("Content-Type",e.content_type),e.requestheaders&&Nt.each(e.requestheaders,function(e){t.setRequestHeader(e.key,e.value)}),t.setRequestHeader("X-Requested-With","XMLHttpRequest"),(t=_w.fire("beforeSend",{xhr:t,settings:e}).xhr).send(e.data),!e.async)return r();Ar.setTimeout(r,10)}}),Aw=Nt.extend,Rw=(Dw.sendRPC=function(e){return(new Dw).send(e)},Dw.prototype.send=function(e){var n=e.error,r=e.success,o=Aw(this.settings,e);o.success=function(e,t){(e=void 0===(e=Ew.parse(e))?{error:"JSON Parse error."}:e).error?n.call(o.error_scope||o.scope,e.error,t):r.call(o.success_scope||o.scope,e.result)},o.error=function(e,t){n&&n.call(o.error_scope||o.scope,e,t)},o.data=Ew.serialize({id:e.id||"c"+this.count++,method:e.method,params:e.params}),o.content_type="application/json",_w.send(o)},Dw);function Dw(e){this.settings=Aw({},e),this.count=0}try{var Tw,Ow="__storage_test__";(Tw=window.localStorage).setItem(Ow,Ow),Tw.removeItem(Ow)}catch(e){yw={},Cw=[],xw={getItem:function(e){return yw[e]||null},setItem:function(e,t){Cw.push(e),yw[e]=String(t)},key:function(e){return Cw[e]},removeItem:function(t){Cw=Cw.filter(function(e){return e===t}),delete yw[t]},clear:function(){Cw=[],yw={}},length:0},Object.defineProperty(xw,"length",{get:function(){return Cw.length},configurable:!1,enumerable:!1}),Tw=xw}var Bw={geom:{Rect:pw},util:{Promise:_r,Delay:Ar,Tools:Nt,VK:If,URI:nv,Class:aw,EventDispatcher:yx,Observable:Ax,I18n:lu,XHR:_w,JSON:Ew,JSONRequest:Rw,JSONP:kw,LocalStorage:Tw,Color:function(e){function t(e){var t;return"object"==typeof e?"r"in e?(u=e.r,s=e.g,c=e.b):"v"in e&&function(e,t,n){if(e=(parseInt(e,10)||0)%360,t=parseInt(t,10)/100,n=parseInt(n,10)/100,t=Sw(0,ww(t,1)),n=Sw(0,ww(n,1)),0!==t){var r=e/60,o=n*t,i=o*(1-Math.abs(r%2-1)),a=n-o;switch(Math.floor(r)){case 0:u=o,s=i,c=0;break;case 1:u=i,s=o,c=0;break;case 2:u=0,s=o,c=i;break;case 3:u=0,s=i,c=o;break;case 4:u=i,s=0,c=o;break;case 5:u=o,s=0,c=i;break;default:u=s=c=0}u=Nw(255*(u+a)),s=Nw(255*(s+a)),c=Nw(255*(c+a))}else u=s=c=Nw(255*n)}(e.h,e.s,e.v):(t=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)[^\)]*\)/gi.exec(e))?(u=parseInt(t[1],10),s=parseInt(t[2],10),c=parseInt(t[3],10)):(t=/#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(e))?(u=parseInt(t[1],16),s=parseInt(t[2],16),c=parseInt(t[3],16)):(t=/#([0-F])([0-F])([0-F])/gi.exec(e))&&(u=parseInt(t[1]+t[1],16),s=parseInt(t[2]+t[2],16),c=parseInt(t[3]+t[3],16)),u=u<0?0:255<u?255:u,s=s<0?0:255<s?255:s,c=c<0?0:255<c?255:c,n}var n={},u=0,s=0,c=0;return e&&t(e),n.toRgb=function(){return{r:u,g:s,b:c}},n.toHsv=function(){return e=u,t=s,n=c,o=0,(i=ww(e/=255,ww(t/=255,n/=255)))===(a=Sw(e,Sw(t,n)))?{h:0,s:0,v:100*(o=i)}:(r=(a-i)/a,{h:Nw(60*((e===i?3:n===i?1:5)-(e===i?t-n:n===i?e-t:n-e)/((o=a)-i))),s:Nw(100*r),v:Nw(100*o)});var e,t,n,r,o,i,a},n.toHex=function(){function e(e){return 1<(e=parseInt(e,10).toString(16)).length?e:"0"+e}return"#"+e(u)+e(s)+e(c)},n.parse=t,n},ImageUploader:function(n){var e=rb(),r=sb(n,e);return{upload:function(e,t){return r.upload(e,(t=void 0===t||t)?ub(n):void 0)}}}},dom:{EventUtils:ci,Sizzle:ca,DomQuery:Ya,TreeWalker:Dr,TextSeeker:Au,DOMUtils:eu,ScriptLoader:ou,RangeUtils:Lf,Serializer:dv,StyleSheetLoader:Sr,ControlSelection:Sf,BookmarkManager:Hl,Selection:Fh,Event:ci.Event},html:{Styles:ao,Entities:Zo,Node:jd,Schema:oo,SaxParser:iv,DomParser:cv,Writer:nm,Serializer:rm},Env:xt,AddOnManager:fu,Annotator:zl,Formatter:mb,UndoManager:pb,EditorCommands:cx,WindowManager:Gv,NotificationManager:Ev,EditorObservable:Dx,Shortcuts:Ix,Editor:Vx,FocusManager:Fd,EditorManager:ow,DOM:eu.DOM,ScriptLoader:ou.ScriptLoader,PluginManager:Xv,ThemeManager:Yv,IconManager:Vv,Resource:hw,trim:Nt.trim,isArray:Nt.isArray,is:Nt.is,toArray:Nt.toArray,makeMap:Nt.makeMap,each:Nt.each,map:Nt.map,grep:Nt.grep,inArray:Nt.inArray,extend:Nt.extend,create:Nt.create,walk:Nt.walk,createNS:Nt.createNS,resolve:Nt.resolve,explode:Nt.explode,_addCacheSuffix:Nt._addCacheSuffix,isOpera:xt.opera,isWebKit:xt.webkit,isIE:xt.ie,isGecko:xt.gecko,isMac:xt.mac},Pw=Nt.extend(ow,Bw),Lw=Pw;window.tinymce=Lw,window.tinyMCE=Lw,function(e){if("object"==typeof module)try{module.exports=e}catch(e){}}(Pw)}(); \ No newline at end of file diff --git a/groups.io/webfonts/fa-sharp-light-300.ttf b/groups.io/webfonts/fa-sharp-light-300.ttf new file mode 100644 index 00000000..37d920ad Binary files /dev/null and b/groups.io/webfonts/fa-sharp-light-300.ttf differ diff --git a/groups.io/webfonts/fa-sharp-light-300.woff2 b/groups.io/webfonts/fa-sharp-light-300.woff2 new file mode 100644 index 00000000..0e1fc63c Binary files /dev/null and b/groups.io/webfonts/fa-sharp-light-300.woff2 differ diff --git a/groups.io/webfonts/fa-sharp-regular-400.ttf b/groups.io/webfonts/fa-sharp-regular-400.ttf new file mode 100644 index 00000000..1b2af509 Binary files /dev/null and b/groups.io/webfonts/fa-sharp-regular-400.ttf differ diff --git a/groups.io/webfonts/fa-sharp-regular-400.woff2 b/groups.io/webfonts/fa-sharp-regular-400.woff2 new file mode 100644 index 00000000..59739960 Binary files /dev/null and b/groups.io/webfonts/fa-sharp-regular-400.woff2 differ diff --git a/groups.io/webfonts/fa-sharp-solid-900.ttf b/groups.io/webfonts/fa-sharp-solid-900.ttf new file mode 100644 index 00000000..f93a2039 Binary files /dev/null and b/groups.io/webfonts/fa-sharp-solid-900.ttf differ diff --git a/groups.io/webfonts/fa-sharp-solid-900.woff2 b/groups.io/webfonts/fa-sharp-solid-900.woff2 new file mode 100644 index 00000000..86f55d51 Binary files /dev/null and b/groups.io/webfonts/fa-sharp-solid-900.woff2 differ